From 7767101bc41608937047156db4e547ce3db096c4 Mon Sep 17 00:00:00 2001 From: davdroman Date: Sun, 28 Jun 2015 22:06:36 +0200 Subject: [PATCH] 2.0.1 release --- Bohr.podspec | 4 +- Bohr/BOButtonTableViewCell.h | 4 ++ Bohr/BOButtonTableViewCell.m | 2 - Bohr/BOChoiceTableViewCell.h | 2 + Bohr/BOChoiceTableViewCell.m | 2 - Bohr/BOOptionTableViewCell.h | 3 +- Bohr/BOOptionTableViewCell.m | 4 +- Bohr/BOSetting.h | 4 ++ Bohr/BOSwitchTableViewCell.h | 4 ++ Bohr/BOTableViewCell+Subclass.h | 14 +++++ Bohr/BOTableViewCell.h | 8 +++ Bohr/BOTableViewCell.m | 17 +----- Bohr/BOTableViewController+Private.h | 4 +- Bohr/BOTableViewController.h | 7 +++ Bohr/BOTableViewController.m | 87 ++++++++++++++-------------- Bohr/BOTextTableViewCell.h | 11 ++++ Bohr/BOTimeTableViewCell.h | 1 + Bohr/BOTimeTableViewCell.m | 8 +-- Bohr/Info.plist | 2 +- BohrDemo/AppDelegate.m | 1 - BohrDemo/Info.plist | 2 +- BohrDemo/Main.storyboard | 4 +- README.md | 4 +- 23 files changed, 117 insertions(+), 82 deletions(-) diff --git a/Bohr.podspec b/Bohr.podspec index 73f15fc..f5c8b58 100755 --- a/Bohr.podspec +++ b/Bohr.podspec @@ -1,9 +1,9 @@ Pod::Spec.new do |s| s.name = "Bohr" - s.version = "2.0.0" + s.version = "2.0.1" s.summary = "Settings screen composing framework" s.homepage = "https://github.com/DavdRoman/Bohr" - s.author = { "David Roman" => "d@vidroman.me" } + s.author = { "David Román" => "d@vidroman.me" } s.license = { :type => 'MIT', :file => 'LICENSE' } s.platform = :ios, '8.0' diff --git a/Bohr/BOButtonTableViewCell.h b/Bohr/BOButtonTableViewCell.h index efece7b..d906127 100644 --- a/Bohr/BOButtonTableViewCell.h +++ b/Bohr/BOButtonTableViewCell.h @@ -10,9 +10,13 @@ @interface BOButtonTableViewCell : BOTableViewCell +/// The target of the cell action. @property (nonatomic) id target; + +/// The action defined by the cell, triggered when it's tapped. @property (nonatomic) SEL action; +/// Sets both the target and action for the cell to be performed. - (void)setTarget:(id)target action:(SEL)action; @end diff --git a/Bohr/BOButtonTableViewCell.m b/Bohr/BOButtonTableViewCell.m index aa1afca..1650112 100644 --- a/Bohr/BOButtonTableViewCell.m +++ b/Bohr/BOButtonTableViewCell.m @@ -20,8 +20,6 @@ - (void)setup { #pragma clang diagnostic ignored "-Warc-performSelector-leaks" - (void)wasSelectedFromViewController:(BOTableViewController *)viewController { - [super wasSelectedFromViewController:viewController]; - if ([self.target respondsToSelector:self.action]) { [self.target performSelector:self.action]; } diff --git a/Bohr/BOChoiceTableViewCell.h b/Bohr/BOChoiceTableViewCell.h index cfe4e41..6874bc5 100644 --- a/Bohr/BOChoiceTableViewCell.h +++ b/Bohr/BOChoiceTableViewCell.h @@ -10,8 +10,10 @@ @interface BOChoiceTableViewCell : BOTableViewCell +/// An array defining (in short) all the options availables on the cell. @property (nonatomic, strong) NSArray *options; +/// An array defining all the footer titles for each option assigned to the cell. @property (nonatomic, strong) IBInspectable NSArray *footerTitles; @end diff --git a/Bohr/BOChoiceTableViewCell.m b/Bohr/BOChoiceTableViewCell.m index 28bd07b..2e0d7cf 100644 --- a/Bohr/BOChoiceTableViewCell.m +++ b/Bohr/BOChoiceTableViewCell.m @@ -27,8 +27,6 @@ - (NSString *)footerTitle { } - (void)wasSelectedFromViewController:(BOTableViewController *)viewController { - [super wasSelectedFromViewController:viewController]; - if (self.accessoryType != UITableViewCellAccessoryDisclosureIndicator) { NSInteger currentOption = [self.setting.value integerValue]; diff --git a/Bohr/BOOptionTableViewCell.h b/Bohr/BOOptionTableViewCell.h index 7558ee5..5242448 100644 --- a/Bohr/BOOptionTableViewCell.h +++ b/Bohr/BOOptionTableViewCell.h @@ -3,13 +3,14 @@ // Bohr // // Created by David Román Aguirre on 21/6/15. -// +// Copyright (c) 2015 David Roman. All rights reserved. // #import "BOTableViewCell.h" @interface BOOptionTableViewCell : BOTableViewCell +/// The string for the footer title when the cell has a checkmark on it. @property (nonatomic, strong) IBInspectable NSString *footerTitle; @end diff --git a/Bohr/BOOptionTableViewCell.m b/Bohr/BOOptionTableViewCell.m index 9903b02..fead4f9 100644 --- a/Bohr/BOOptionTableViewCell.m +++ b/Bohr/BOOptionTableViewCell.m @@ -3,7 +3,7 @@ // Bohr // // Created by David Román Aguirre on 21/6/15. -// +// Copyright (c) 2015 David Roman. All rights reserved. // #import "BOOptionTableViewCell.h" @@ -17,8 +17,6 @@ - (void)setup { } - (void)wasSelectedFromViewController:(BOTableViewController *)viewController { - [super wasSelectedFromViewController:viewController]; - NSInteger optionIndex = [viewController.tableView indexPathForCell:self].row; self.setting.value = @(optionIndex); } diff --git a/Bohr/BOSetting.h b/Bohr/BOSetting.h index 5ab1df5..b2f2530 100644 --- a/Bohr/BOSetting.h +++ b/Bohr/BOSetting.h @@ -10,9 +10,13 @@ @interface BOSetting : NSObject +/// The NSUserDefaults key for the cell. @property (nonatomic, readonly) NSString *key; + +/// The NSUserDefaults value assigned for the key defined on the cell. @property (nonatomic, assign) id value; +/// Instantiates a new BOSetting object with a key. + (instancetype)settingWithKey:(NSString *)key; @end diff --git a/Bohr/BOSwitchTableViewCell.h b/Bohr/BOSwitchTableViewCell.h index e50ae6b..0d87a5f 100644 --- a/Bohr/BOSwitchTableViewCell.h +++ b/Bohr/BOSwitchTableViewCell.h @@ -10,9 +10,13 @@ @interface BOSwitchTableViewCell : BOTableViewCell +/// The switch on the cell. @property (nonatomic, strong) UISwitch *toggleSwitch; +/// The footer title when the toggle switch is on. @property (nonatomic, strong) IBInspectable NSString *onFooterTitle; + +/// The footer title when the toggle switch is off. @property (nonatomic, strong) IBInspectable NSString *offFooterTitle; @end diff --git a/Bohr/BOTableViewCell+Subclass.h b/Bohr/BOTableViewCell+Subclass.h index dfba853..82592ea 100644 --- a/Bohr/BOTableViewCell+Subclass.h +++ b/Bohr/BOTableViewCell+Subclass.h @@ -13,14 +13,28 @@ @interface BOTableViewCell () +/// The current index path of the cell relative to its table view. @property (nonatomic, strong) NSIndexPath *indexPath; + +/// The setting object which the cell represents. @property (nonatomic, strong) BOSetting *setting; +/// The setup method for the cell, where you may set up all the views and constraints necessary for the cell to work. - (void)setup; + +/// The method in charge of updating the appearance of the main cell view components, through properties as mainColor, mainFont, secondaryColor, secondaryFont. - (void)updateAppearance; + +/// You may return the height for the cell to be expanded when tapped. - (CGFloat)expansionHeight; + +/// You may return the footer text for the cell to be set on its section. - (NSString *)footerTitle; + +/// This method gets called whenever a cell gets selected, passing its parent view controller as an argument. - (void)wasSelectedFromViewController:(BOTableViewController *)viewController; + +/// This method gets called when the cell setting value gets changed externally, so that such change can be represented on the cell. - (void)settingValueDidChange; @end diff --git a/Bohr/BOTableViewCell.h b/Bohr/BOTableViewCell.h index f89234b..4c5a021 100644 --- a/Bohr/BOTableViewCell.h +++ b/Bohr/BOTableViewCell.h @@ -10,14 +10,22 @@ @interface BOTableViewCell : UITableViewCell +/// The NSUserDefaults key associated with the cell. @property (nonatomic, strong) IBInspectable NSString *key; +/// The main text color for the cell. @property (nonatomic, strong) IBInspectable UIColor *mainColor; + +/// The main text font for the cell. @property (nonatomic, strong) UIFont *mainFont; // Apple pls rdar://19973159 +/// The secondary or detail text color for the cell. @property (nonatomic, strong) IBInspectable UIColor *secondaryColor; + +/// The secondary or detail text font for the cell. @property (nonatomic, strong) UIFont *secondaryFont; +/// The color for the selected state of the cell. @property (nonatomic, strong) IBInspectable UIColor *selectedColor; @end diff --git a/Bohr/BOTableViewCell.m b/Bohr/BOTableViewCell.m index 100fed9..bd1a22e 100644 --- a/Bohr/BOTableViewCell.m +++ b/Bohr/BOTableViewCell.m @@ -70,22 +70,7 @@ - (void)setupConstraints {} - (void)updateAppearance {} - (CGFloat)expansionHeight {return 0;} - (NSString *)footerTitle {return nil;} - -- (void)wasSelectedFromViewController:(BOTableViewController *)viewController { - if (self.expansionHeight > 0) { - viewController.expansionIndexPath = ![self.indexPath isEqual:viewController.expansionIndexPath] ? self.indexPath : nil; - - [viewController.tableView deselectRowAtIndexPath:self.indexPath animated:NO]; - [viewController.tableView beginUpdates]; - [viewController.tableView endUpdates]; - [viewController.tableView scrollToRowAtIndexPath:self.indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; - } else { - if (self.accessoryType != UITableViewCellAccessoryDisclosureIndicator) { - [viewController.tableView deselectRowAtIndexPath:self.indexPath animated:YES]; - } - } -} - +- (void)wasSelectedFromViewController:(BOTableViewController *)viewController {} - (void)settingValueDidChange {} @end diff --git a/Bohr/BOTableViewController+Private.h b/Bohr/BOTableViewController+Private.h index cf155c5..79fd4c1 100644 --- a/Bohr/BOTableViewController+Private.h +++ b/Bohr/BOTableViewController+Private.h @@ -1,9 +1,9 @@ // // BOTableViewController+Private.h -// +// Bohr // // Created by David Roman on 24/6/15. -// +// Copyright (c) 2015 David Roman. All rights reserved. // #import "BOTableViewController.h" diff --git a/Bohr/BOTableViewController.h b/Bohr/BOTableViewController.h index eef6fa3..d59e651 100644 --- a/Bohr/BOTableViewController.h +++ b/Bohr/BOTableViewController.h @@ -10,12 +10,19 @@ @interface BOTableViewController : UITableViewController +/// The text color for all the headers in the table view. @property (nonatomic, strong) IBInspectable UIColor *headerTitlesColor; + +/// The text font for all the headers in the table view. @property (nonatomic, strong) UIFont *headerTitlesFont; +/// The text color for all the footers in the table view. @property (nonatomic, strong) IBInspectable UIColor *footerTitlesColor; + +/// The text font for all the footers in the table view. @property (nonatomic, strong) UIFont *footerTitlesFont; +/// The setup method for the controller. - (void)setup; @end diff --git a/Bohr/BOTableViewController.m b/Bohr/BOTableViewController.m index 2bfadc8..6e62f04 100644 --- a/Bohr/BOTableViewController.m +++ b/Bohr/BOTableViewController.m @@ -34,31 +34,11 @@ - (void)tableViewReceivedTap { [self.tableView endEditing:YES]; } -- (NSArray *)footerViews { - if (!_footerViews) { - _footerViews = [NSArray new]; - - for (NSInteger i = 0; i < [self.tableView numberOfSections]; i++) { - NSString *footerTitle = [self tableView:self.tableView titleForFooterInSection:i]; - - if (footerTitle) { - UITableViewHeaderFooterView *footerView = [UITableViewHeaderFooterView new]; - _footerViews = [_footerViews arrayByAddingObject:footerView]; - } else { - _footerViews = [_footerViews arrayByAddingObject:[NSNull null]]; - } - } - } - - return _footerViews; -} +// Apple pls http://blog.supertop.co/post/80781694515/viewmightappear - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; - [self.tableView beginUpdates]; - [self.tableView endUpdates]; - NSIndexPath *selectedRowIndexPath = [self.tableView indexPathForSelectedRow]; if (selectedRowIndexPath) { @@ -72,7 +52,7 @@ - (void)viewWillAppear:(BOOL)animated { } } -// Apple pls http://blog.supertop.co/post/80781694515/viewmightappear +#pragma mark Headers & cells - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; @@ -118,49 +98,65 @@ - (void)tableView:(UITableView *)tableView willDisplayCell:(BOTableViewCell *)ce } } -- (void)reloadTableView { - [UIView performWithoutAnimation:^{ - [self updateFooters]; +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + BOTableViewCell *cell = (BOTableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; + + if (cell.expansionHeight > 0) { + self.expansionIndexPath = ![cell.indexPath isEqual:self.expansionIndexPath] ? cell.indexPath : nil; + + [self.tableView deselectRowAtIndexPath:cell.indexPath animated:NO]; [self.tableView beginUpdates]; [self.tableView endUpdates]; - }]; + [self.tableView scrollToRowAtIndexPath:cell.indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; + } else { + if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) { + [self.tableView deselectRowAtIndexPath:cell.indexPath animated:YES]; + } + } + + if ([cell respondsToSelector:@selector(wasSelectedFromViewController:)]) [cell wasSelectedFromViewController:self]; } -- (void)updateFooters { - for (NSInteger i = 0; i < [self.tableView numberOfSections]; i++) { - NSString *footerTitle = [self tableView:self.tableView titleForFooterInSection:i]; - UITableViewHeaderFooterView *footerView = self.footerViews[i]; - if (![footerView isEqual:[NSNull null]]) { - footerView.textLabel.text = footerTitle; - [footerView sizeToFit]; +#pragma mark Dynamic footers + +- (NSArray *)footerViews { + if (!_footerViews) { + _footerViews = [NSArray new]; + + for (NSInteger i = 0; i < [self.tableView numberOfSections]; i++) { + UITableViewHeaderFooterView *footerView = [UITableViewHeaderFooterView new]; + _footerViews = [_footerViews arrayByAddingObject:footerView]; } } + + return _footerViews; } -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - BOTableViewCell *cell = (BOTableViewCell *)[tableView cellForRowAtIndexPath:indexPath]; - if ([cell respondsToSelector:@selector(wasSelectedFromViewController:)]) [cell wasSelectedFromViewController:self]; +- (void)reloadTableView { + [UIView performWithoutAnimation:^{ + [self.tableView beginUpdates]; + [self.tableView endUpdates]; + }]; } -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { UITableViewHeaderFooterView *footerView = self.footerViews[section]; + footerView.textLabel.text = [self tableView:tableView titleForFooterInSection:section]; - if (![footerView isEqual:[NSNull null]]) { - footerView.textLabel.text = [self tableView:tableView titleForFooterInSection:section]; - return footerView; - } - - return nil; + return [super tableView:tableView heightForFooterInSection:section]; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section { + // First, we get the super value, and if it's nil we set it to an empty string (this is the lowest priority for dynamic footers). NSString *footerTitle = [super tableView:self.tableView titleForFooterInSection:section]; if (!footerTitle) footerTitle = @""; + // Next, we try to find an existing footer in the last cell of the section (this is the medium priority for dynamic footers). NSInteger numberOfRows = [super tableView:self.tableView numberOfRowsInSection:section]; BOTableViewCell *lastCell = (BOTableViewCell *)[super tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:numberOfRows-1 inSection:section]]; if ([lastCell isKindOfClass:[BOTableViewCell class]] && [lastCell footerTitle]) footerTitle = [lastCell footerTitle]; + // Finally, we try to find an existing footer in any cell that has a checkmark accessory on it (this is the top priority for dynamic footers). for (NSInteger i = 0; i < numberOfRows; i++) { BOTableViewCell *cell = (BOTableViewCell *)[super tableView:self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:section]]; @@ -172,6 +168,11 @@ - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInte return footerTitle; } +- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { + UITableViewHeaderFooterView *footerView = self.footerViews[section]; + return footerView; +} + - (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section { UITableViewHeaderFooterView *footer = (UITableViewHeaderFooterView *)view; diff --git a/Bohr/BOTextTableViewCell.h b/Bohr/BOTextTableViewCell.h index 064cb68..fdbbbf3 100644 --- a/Bohr/BOTextTableViewCell.h +++ b/Bohr/BOTextTableViewCell.h @@ -8,17 +8,28 @@ #import "BOTableViewCell.h" +/// Defines an error after trying to input some new value to the cell text field. typedef NS_ENUM(NSInteger, BOTextFieldInputError) { BOTextFieldInputTooShortError }; @interface BOTextTableViewCell : BOTableViewCell +/** + * Block type defining an input error that has ocurred in the cell text field. + * + * @param cell the cell affected by the input error. + * @param error the received input error. + */ typedef void(^BOTextFieldInputErrorBlock)(BOTextTableViewCell *cell, BOTextFieldInputError error); +/// The text field on the cell. @property (nonatomic, strong) UITextField *textField; +/// The minimum amount of non-blank characters necessary for the text field. @property (nonatomic) IBInspectable NSInteger minimumTextLength; + +/// A block defining an input error that has ocurred in the cell text field. @property (nonatomic, copy) BOTextFieldInputErrorBlock inputErrorBlock; @end diff --git a/Bohr/BOTimeTableViewCell.h b/Bohr/BOTimeTableViewCell.h index ee7d9ef..c2f50c9 100644 --- a/Bohr/BOTimeTableViewCell.h +++ b/Bohr/BOTimeTableViewCell.h @@ -10,6 +10,7 @@ @interface BOTimeTableViewCell : BOTableViewCell +/// The minute interval showed on the time picker view. @property (nonatomic) IBInspectable NSInteger minuteInterval; @end diff --git a/Bohr/BOTimeTableViewCell.m b/Bohr/BOTimeTableViewCell.m index 6a680dd..c92b9b1 100644 --- a/Bohr/BOTimeTableViewCell.m +++ b/Bohr/BOTimeTableViewCell.m @@ -70,11 +70,11 @@ - (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forC switch (component) { case 0: - title = [NSString stringWithFormat:@"%@%li", row < 10 ? @"0" : @"", row]; + title = [NSString stringWithFormat:@"%@%li", row < 10 ? @"0" : @"", (long)row]; break; case 1: - title = [NSString stringWithFormat:@"%@%li", row*self.minuteInterval < 10 ? @"0" : @"", row*self.minuteInterval]; + title = [NSString stringWithFormat:@"%@%li", row*self.minuteInterval < 10 ? @"0" : @"", (long)(row*self.minuteInterval)]; break; } @@ -133,8 +133,8 @@ - (NSString *)timeStringForSettingValue { NSInteger hours = [self hoursForSettingValue]; NSInteger minutes = [self minutesForSettingValue]; - NSString *hoursString = [[NSString alloc] initWithFormat:@"%@%li", hours < 10 ? @"0" : @"", hours]; - NSString *minutesString = [[NSString alloc] initWithFormat:@"%@%li", minutes < 10 ? @"0" : @"", minutes]; + NSString *hoursString = [[NSString alloc] initWithFormat:@"%@%li", hours < 10 ? @"0" : @"", (long)hours]; + NSString *minutesString = [[NSString alloc] initWithFormat:@"%@%li", minutes < 10 ? @"0" : @"", (long)minutes]; NSString *timeString = [[NSString alloc] initWithFormat:@"%@:%@", hoursString, minutesString]; diff --git a/Bohr/Info.plist b/Bohr/Info.plist index d3c0960..be8ad3b 100644 --- a/Bohr/Info.plist +++ b/Bohr/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.0.0 + 2.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/BohrDemo/AppDelegate.m b/BohrDemo/AppDelegate.m index 86d3cef..aaedadc 100644 --- a/BohrDemo/AppDelegate.m +++ b/BohrDemo/AppDelegate.m @@ -12,7 +12,6 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [self setupAppearance]; [self setupDefaults]; diff --git a/BohrDemo/Info.plist b/BohrDemo/Info.plist index 252b32d..c0a78dc 100644 --- a/BohrDemo/Info.plist +++ b/BohrDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.0.0 + 2.0.1 CFBundleSignature ???? CFBundleVersion diff --git a/BohrDemo/Main.storyboard b/BohrDemo/Main.storyboard index 061e02b..7c4f38f 100644 --- a/BohrDemo/Main.storyboard +++ b/BohrDemo/Main.storyboard @@ -12,7 +12,7 @@ - + @@ -244,7 +244,7 @@ - + diff --git a/README.md b/README.md index 9c744d4..1c76d16 100644 --- a/README.md +++ b/README.md @@ -44,7 +44,7 @@ The settings screen you're going to set up is represented by a `UITableViewContr PNG 1

-Set the `UITableViewController` class to `BOTableViewController` o a subclass of it. +Set the `UITableViewController` class to `BOTableViewController` or a subclass of it.

PNG 2 @@ -76,7 +76,7 @@ Finally, set the key of the cell to the desired value. #### Built-in BOTableViewCell's -As mentioned before, there's a bunch of built-in BOTableViewCell subclasses ready to be used: +As mentioned before, there's a bunch of built-in `BOTableViewCell` subclasses ready to be used: - `BOSwitchTableViewCell`: manages `BOOL` values through a `UISwitch` control. - `BOTextTableViewCell`: manages `NSString` values through a `UITextField` control.