diff --git a/Bohr.podspec b/Bohr.podspec index 542b980..6232846 100755 --- a/Bohr.podspec +++ b/Bohr.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "Bohr" - s.version = "2.1.0" + s.version = "3.0.0-alpha.1" s.summary = "Settings screen composing framework" s.homepage = "https://github.com/DavdRoman/Bohr" s.author = { "David Román" => "d@vidroman.me" } diff --git a/Bohr.xcodeproj/project.pbxproj b/Bohr.xcodeproj/project.pbxproj index 3221b66..fa1b475 100644 --- a/Bohr.xcodeproj/project.pbxproj +++ b/Bohr.xcodeproj/project.pbxproj @@ -12,7 +12,6 @@ 754E568A1B1DFDB400075B6E /* BOSetting.m in Sources */ = {isa = PBXBuildFile; fileRef = 754E56881B1DFDB400075B6E /* BOSetting.m */; }; 754E568D1B1FC16700075B6E /* BOSwitchTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 754E568B1B1FC16700075B6E /* BOSwitchTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 754E568E1B1FC16700075B6E /* BOSwitchTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 754E568C1B1FC16700075B6E /* BOSwitchTableViewCell.m */; }; - 7599AF461B2B29E000B253CD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7599AF451B2B29E000B253CD /* Main.storyboard */; }; 759E1B001B2BC31700AD8F38 /* BOTimeTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 754E56931B2083DE00075B6E /* BOTimeTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 759E1B011B2BC31700AD8F38 /* BOTimeTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 754E56941B2083DE00075B6E /* BOTimeTableViewCell.m */; }; 75B6CE1C1B3756D800DADCBD /* BOOptionTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 75B6CE1A1B3756D800DADCBD /* BOOptionTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; @@ -35,6 +34,15 @@ 75E19B451B2BC76100C03FF6 /* BOChoiceTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 754E56A31B20D2FE00075B6E /* BOChoiceTableViewCell.m */; }; 75E19B461B2BCCFE00C03FF6 /* BOTextTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 75E02FE11B21F72C009698D3 /* BOTextTableViewCell.h */; settings = {ATTRIBUTES = (Public, ); }; }; 75E19B471B2BCCFE00C03FF6 /* BOTextTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 75E02FE21B21F72C009698D3 /* BOTextTableViewCell.m */; }; + D5CF66461B8DFAC800FC5F13 /* BOTableViewSection.h in Headers */ = {isa = PBXBuildFile; fileRef = D5CF66441B8DFAC800FC5F13 /* BOTableViewSection.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D5CF66471B8DFAC800FC5F13 /* BOTableViewSection.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CF66451B8DFAC800FC5F13 /* BOTableViewSection.m */; }; + D5CF664C1B8DFF4700FC5F13 /* MZAppearance.h in Headers */ = {isa = PBXBuildFile; fileRef = D5CF66481B8DFF4700FC5F13 /* MZAppearance.h */; settings = {ATTRIBUTES = (Public, ); }; }; + D5CF664D1B8DFF4700FC5F13 /* MZAppearance.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CF66491B8DFF4700FC5F13 /* MZAppearance.m */; }; + D5CF664E1B8DFF4700FC5F13 /* NSInvocation+Copy.h in Headers */ = {isa = PBXBuildFile; fileRef = D5CF664A1B8DFF4700FC5F13 /* NSInvocation+Copy.h */; }; + D5CF664F1B8DFF4700FC5F13 /* NSInvocation+Copy.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CF664B1B8DFF4700FC5F13 /* NSInvocation+Copy.m */; }; + D5CF66521B8E491A00FC5F13 /* UIColor+Bohr.m in Sources */ = {isa = PBXBuildFile; fileRef = D5CF66511B8E491A00FC5F13 /* UIColor+Bohr.m */; }; + D5D00B6E1B8FD14500ADCAB2 /* OptionsTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D5D00B6D1B8FD14500ADCAB2 /* OptionsTableViewController.m */; }; + D5D00B721B8FE63E00ADCAB2 /* BOTableViewCell+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D5D00B711B8FE63E00ADCAB2 /* BOTableViewCell+Private.h */; }; D5F1D8A91B3A1EF1004DA018 /* BOTableViewController+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D5F1D8A81B3A1EF1004DA018 /* BOTableViewController+Private.h */; }; D5F1D8AB1B3A210E004DA018 /* BOSetting+Private.h in Headers */ = {isa = PBXBuildFile; fileRef = D5F1D8AA1B3A210E004DA018 /* BOSetting+Private.h */; }; /* End PBXBuildFile section */ @@ -75,7 +83,6 @@ 754E56981B20C9D400075B6E /* BOButtonTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOButtonTableViewCell.m; sourceTree = ""; }; 754E56A21B20D2FE00075B6E /* BOChoiceTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BOChoiceTableViewCell.h; sourceTree = ""; }; 754E56A31B20D2FE00075B6E /* BOChoiceTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOChoiceTableViewCell.m; sourceTree = ""; }; - 7599AF451B2B29E000B253CD /* Main.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Main.storyboard; sourceTree = ""; }; 75B6CE1A1B3756D800DADCBD /* BOOptionTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BOOptionTableViewCell.h; sourceTree = ""; }; 75B6CE1B1B3756D800DADCBD /* BOOptionTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOOptionTableViewCell.m; sourceTree = ""; }; 75C7ADD31B1AB3010050C8AA /* BohrDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = BohrDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; @@ -96,6 +103,17 @@ 75C7AE261B1AB42A0050C8AA /* BOTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOTableViewCell.m; sourceTree = ""; }; 75E02FE11B21F72C009698D3 /* BOTextTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BOTextTableViewCell.h; sourceTree = ""; }; 75E02FE21B21F72C009698D3 /* BOTextTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOTextTableViewCell.m; sourceTree = ""; }; + D5CF66441B8DFAC800FC5F13 /* BOTableViewSection.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BOTableViewSection.h; sourceTree = ""; }; + D5CF66451B8DFAC800FC5F13 /* BOTableViewSection.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BOTableViewSection.m; sourceTree = ""; }; + D5CF66481B8DFF4700FC5F13 /* MZAppearance.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MZAppearance.h; sourceTree = ""; }; + D5CF66491B8DFF4700FC5F13 /* MZAppearance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MZAppearance.m; sourceTree = ""; }; + D5CF664A1B8DFF4700FC5F13 /* NSInvocation+Copy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSInvocation+Copy.h"; sourceTree = ""; }; + D5CF664B1B8DFF4700FC5F13 /* NSInvocation+Copy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSInvocation+Copy.m"; sourceTree = ""; }; + D5CF66501B8E491A00FC5F13 /* UIColor+Bohr.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIColor+Bohr.h"; sourceTree = ""; }; + D5CF66511B8E491A00FC5F13 /* UIColor+Bohr.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIColor+Bohr.m"; sourceTree = ""; }; + D5D00B6C1B8FD14500ADCAB2 /* OptionsTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OptionsTableViewController.h; sourceTree = ""; }; + D5D00B6D1B8FD14500ADCAB2 /* OptionsTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = OptionsTableViewController.m; sourceTree = ""; }; + D5D00B711B8FE63E00ADCAB2 /* BOTableViewCell+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BOTableViewCell+Private.h"; sourceTree = ""; }; D5F1D8A81B3A1EF1004DA018 /* BOTableViewController+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BOTableViewController+Private.h"; sourceTree = ""; }; D5F1D8AA1B3A210E004DA018 /* BOSetting+Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "BOSetting+Private.h"; sourceTree = ""; }; /* End PBXFileReference section */ @@ -142,9 +160,12 @@ children = ( 75C7ADDA1B1AB3010050C8AA /* AppDelegate.h */, 75C7ADDB1B1AB3010050C8AA /* AppDelegate.m */, - 7599AF451B2B29E000B253CD /* Main.storyboard */, + D5CF66501B8E491A00FC5F13 /* UIColor+Bohr.h */, + D5CF66511B8E491A00FC5F13 /* UIColor+Bohr.m */, 75C7ADDD1B1AB3010050C8AA /* TableViewController.h */, 75C7ADDE1B1AB3010050C8AA /* TableViewController.m */, + D5D00B6C1B8FD14500ADCAB2 /* OptionsTableViewController.h */, + D5D00B6D1B8FD14500ADCAB2 /* OptionsTableViewController.m */, 75C7ADD61B1AB3010050C8AA /* Supporting Files */, ); path = BohrDemo; @@ -168,8 +189,11 @@ 75C7AE1F1B1AB3480050C8AA /* BOTableViewController.h */, 75C7AE201B1AB3480050C8AA /* BOTableViewController.m */, D5F1D8A81B3A1EF1004DA018 /* BOTableViewController+Private.h */, + D5CF66441B8DFAC800FC5F13 /* BOTableViewSection.h */, + D5CF66451B8DFAC800FC5F13 /* BOTableViewSection.m */, 75C7AE251B1AB42A0050C8AA /* BOTableViewCell.h */, 75C7AE261B1AB42A0050C8AA /* BOTableViewCell.m */, + D5D00B711B8FE63E00ADCAB2 /* BOTableViewCell+Private.h */, 754E564F1B1B461700075B6E /* BOTableViewCell+Subclass.h */, 754E568B1B1FC16700075B6E /* BOSwitchTableViewCell.h */, 754E568C1B1FC16700075B6E /* BOSwitchTableViewCell.m */, @@ -186,6 +210,10 @@ 754E56871B1DFDB400075B6E /* BOSetting.h */, 754E56881B1DFDB400075B6E /* BOSetting.m */, D5F1D8AA1B3A210E004DA018 /* BOSetting+Private.h */, + D5CF66481B8DFF4700FC5F13 /* MZAppearance.h */, + D5CF66491B8DFF4700FC5F13 /* MZAppearance.m */, + D5CF664A1B8DFF4700FC5F13 /* NSInvocation+Copy.h */, + D5CF664B1B8DFF4700FC5F13 /* NSInvocation+Copy.m */, 75C7AE011B1AB3280050C8AA /* Supporting Files */, ); path = Bohr; @@ -213,7 +241,11 @@ 75C7AE211B1AB3480050C8AA /* BOTableViewController.h in Headers */, 75E19B441B2BC76100C03FF6 /* BOChoiceTableViewCell.h in Headers */, 754E56891B1DFDB400075B6E /* BOSetting.h in Headers */, + D5CF66461B8DFAC800FC5F13 /* BOTableViewSection.h in Headers */, + D5CF664C1B8DFF4700FC5F13 /* MZAppearance.h in Headers */, 754E568D1B1FC16700075B6E /* BOSwitchTableViewCell.h in Headers */, + D5D00B721B8FE63E00ADCAB2 /* BOTableViewCell+Private.h in Headers */, + D5CF664E1B8DFF4700FC5F13 /* NSInvocation+Copy.h in Headers */, 75B6CE1C1B3756D800DADCBD /* BOOptionTableViewCell.h in Headers */, 75C7AE291B1AB42A0050C8AA /* BOTableViewCell.h in Headers */, 759E1B001B2BC31700AD8F38 /* BOTimeTableViewCell.h in Headers */, @@ -268,15 +300,15 @@ 75C7ADC91B1AB2F80050C8AA /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 0630; + LastUpgradeCheck = 0640; TargetAttributes = { 75C7ADD21B1AB3010050C8AA = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = 928NVD8D9L; + DevelopmentTeam = 26CPNYHDUU; }; 75C7ADFE1B1AB3280050C8AA = { CreatedOnToolsVersion = 6.3.2; - DevelopmentTeam = 928NVD8D9L; + DevelopmentTeam = 26CPNYHDUU; }; }; }; @@ -304,7 +336,6 @@ isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( - 7599AF461B2B29E000B253CD /* Main.storyboard in Resources */, 75C7ADE71B1AB3010050C8AA /* LaunchScreen.xib in Resources */, 75C7ADE41B1AB3010050C8AA /* Images.xcassets in Resources */, ); @@ -324,9 +355,11 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + D5CF66521B8E491A00FC5F13 /* UIColor+Bohr.m in Sources */, 75C7ADDF1B1AB3010050C8AA /* TableViewController.m in Sources */, 75C7ADDC1B1AB3010050C8AA /* AppDelegate.m in Sources */, 75C7ADD91B1AB3010050C8AA /* main.m in Sources */, + D5D00B6E1B8FD14500ADCAB2 /* OptionsTableViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -338,11 +371,14 @@ 75C7AE221B1AB3480050C8AA /* BOTableViewController.m in Sources */, 754E568A1B1DFDB400075B6E /* BOSetting.m in Sources */, 75B6CE1F1B375DCA00DADCBD /* BOButtonTableViewCell.m in Sources */, + D5CF66471B8DFAC800FC5F13 /* BOTableViewSection.m in Sources */, 754E568E1B1FC16700075B6E /* BOSwitchTableViewCell.m in Sources */, 759E1B011B2BC31700AD8F38 /* BOTimeTableViewCell.m in Sources */, + D5CF664D1B8DFF4700FC5F13 /* MZAppearance.m in Sources */, 75B6CE1D1B3756D800DADCBD /* BOOptionTableViewCell.m in Sources */, 75E19B471B2BCCFE00C03FF6 /* BOTextTableViewCell.m in Sources */, 75E19B451B2BC76100C03FF6 /* BOChoiceTableViewCell.m in Sources */, + D5CF664F1B8DFF4700FC5F13 /* NSInvocation+Copy.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -371,12 +407,15 @@ 75C7ADCD1B1AB2F80050C8AA /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 8.0; + ONLY_ACTIVE_ARCH = YES; }; name = Debug; }; 75C7ADCE1B1AB2F80050C8AA /* Release */ = { isa = XCBuildConfiguration; buildSettings = { + IPHONEOS_DEPLOYMENT_TARGET = 8.0; }; name = Release; }; @@ -419,7 +458,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = BohrDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -463,7 +502,7 @@ GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = BohrDemo/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -518,7 +557,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Bohr/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; @@ -570,7 +609,7 @@ GCC_WARN_UNUSED_VARIABLE = YES; INFOPLIST_FILE = Bohr/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.3; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; MTL_ENABLE_DEBUG_INFO = NO; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Bohr.xcodeproj/xcshareddata/xcschemes/Bohr.xcscheme b/Bohr.xcodeproj/xcshareddata/xcschemes/Bohr.xcscheme index d010ad1..3f59c01 100644 --- a/Bohr.xcodeproj/xcshareddata/xcschemes/Bohr.xcscheme +++ b/Bohr.xcodeproj/xcshareddata/xcschemes/Bohr.xcscheme @@ -1,6 +1,6 @@ +#import "MZAppearance.h" + +@interface BOTableViewCell : UITableViewCell + +/// The NSUserDefaults key associated with the cell. +@property (nonatomic) NSString *key; + +/// The main text color for the cell. +@property (nonatomic) UIColor *mainColor UI_APPEARANCE_SELECTOR; + +/// The main text font for the cell. +@property (nonatomic) UIFont *mainFont UI_APPEARANCE_SELECTOR; + +/// The secondary or detail text color for the cell. +@property (nonatomic) UIColor *secondaryColor UI_APPEARANCE_SELECTOR; + +/// The secondary or detail text font for the cell. +@property (nonatomic) UIFont *secondaryFont UI_APPEARANCE_SELECTOR; + +/// The color for the selected state of the cell. +@property (nonatomic) UIColor *selectedColor UI_APPEARANCE_SELECTOR; + +/// The default footer title for the cell. +@property (nonatomic) NSString *footerTitle; + ++ (instancetype)cellWithTitle:(NSString *)title key:(NSString *)key handler:(void (^)(id cell))handler; + +@end diff --git a/Bohr/BOTableViewCell+Private.h b/Bohr/BOTableViewCell+Private.h new file mode 100644 index 0000000..160d635 --- /dev/null +++ b/Bohr/BOTableViewCell+Private.h @@ -0,0 +1,15 @@ +// +// BOTableViewCell+Private.h +// Bohr +// +// Created by David Román Aguirre on 28/08/15. +// +// + +#import "BOTableViewCell.h" + +@interface BOTableViewCell () + +- (void)_updateAppearance; + +@end diff --git a/Bohr/BOTableViewCell+Subclass.h b/Bohr/BOTableViewCell+Subclass.h index 82592ea..eed957c 100644 --- a/Bohr/BOTableViewCell+Subclass.h +++ b/Bohr/BOTableViewCell+Subclass.h @@ -14,10 +14,10 @@ @interface BOTableViewCell () /// The current index path of the cell relative to its table view. -@property (nonatomic, strong) NSIndexPath *indexPath; +@property (nonatomic) NSIndexPath *indexPath; /// The setting object which the cell represents. -@property (nonatomic, strong) BOSetting *setting; +@property (nonatomic) 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; diff --git a/Bohr/BOTableViewCell.h b/Bohr/BOTableViewCell.h index 0e64ba8..11fbe3c 100644 --- a/Bohr/BOTableViewCell.h +++ b/Bohr/BOTableViewCell.h @@ -7,28 +7,37 @@ // #import +#import "MZAppearance.h" @interface BOTableViewCell : UITableViewCell /// The NSUserDefaults key associated with the cell. -@property (nonatomic, strong) IBInspectable NSString *key; +@property (nonatomic) NSString *key; /// The main text color for the cell. -@property (nonatomic, strong) IBInspectable UIColor *mainColor; +@property (nonatomic) UIColor *mainColor UI_APPEARANCE_SELECTOR; /// The main text font for the cell. -@property (nonatomic, strong) UIFont *mainFont; // Apple pls rdar://19973159 +@property (nonatomic) UIFont *mainFont UI_APPEARANCE_SELECTOR; /// The secondary or detail text color for the cell. -@property (nonatomic, strong) IBInspectable UIColor *secondaryColor; +@property (nonatomic) UIColor *secondaryColor UI_APPEARANCE_SELECTOR; /// The secondary or detail text font for the cell. -@property (nonatomic, strong) UIFont *secondaryFont; +@property (nonatomic) UIFont *secondaryFont UI_APPEARANCE_SELECTOR; /// The color for the selected state of the cell. -@property (nonatomic, strong) IBInspectable UIColor *selectedColor; - -/// The default footer title for the cell. -@property (nonatomic, strong) IBInspectable NSString *defaultFooterTitle; +@property (nonatomic) UIColor *selectedColor UI_APPEARANCE_SELECTOR; + +/// An optional destination view controller to push when the cell is pressed. +@property (nonatomic) UIViewController *destinationViewController; + +/** Initializes a new BOTableViewCell object. + * + * @param title The cell title. + * @param key The NSUserDefaults key associated with the cell. + * @param handler A block passed in order to set up anything in the cell. + **/ ++ (instancetype)cellWithTitle:(NSString *)title key:(NSString *)key handler:(void (^)(id cell))handler; @end diff --git a/Bohr/BOTableViewCell.m b/Bohr/BOTableViewCell.m index 8f9a1b1..ca84a8f 100644 --- a/Bohr/BOTableViewCell.m +++ b/Bohr/BOTableViewCell.m @@ -8,59 +8,64 @@ #import "BOTableViewCell+Subclass.h" +#import "BOTableViewCell+Private.h" #import "BOSetting+Private.h" #import "BOTableViewController+Private.h" @implementation BOTableViewCell -- (void)awakeFromNib { - self.clipsToBounds = YES; - self.selectionStyle = UITableViewCellSelectionStyleNone; - self.detailTextLabel.text = nil; - if (self.key) self.setting = [BOSetting settingWithKey:self.key]; - [self setup]; +- (instancetype)initWithTitle:(NSString *)title key:(NSString *)key handler:(void (^)(id cell))handler { + if (self = [self initWithStyle:(key ? UITableViewCellStyleValue1 : UITableViewCellStyleDefault) reuseIdentifier:nil]) { + self.selectionStyle = UITableViewCellSelectionStyleNone; + [self setup]; + if (handler) handler(self); + self.clipsToBounds = YES; + self.textLabel.numberOfLines = 0; + self.textLabel.text = title; + self.textLabel.highlightedTextColor = [UIColor whiteColor]; + self.detailTextLabel.highlightedTextColor = [UIColor whiteColor]; + self.key = key; + self.setting = [BOSetting settingWithKey:self.key]; + } + + return self; +} + +- (void)setDestinationViewController:(UIViewController *)destinationViewController { + if (_destinationViewController != destinationViewController) { + _destinationViewController = destinationViewController; + self.accessoryType = destinationViewController ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone; + } +} + ++ (instancetype)cellWithTitle:(NSString *)title key:(NSString *)key handler:(void (^)(id cell))handler { + return [[self alloc] initWithTitle:title key:key handler:handler]; } - (void)layoutSubviews { [super layoutSubviews]; - if (self.expansionHeight > 0 || self.contentView.subviews.count > 1) { + if (self.expansionHeight > 0) { CGFloat yOffset = (self.layoutMargins.top-self.frame.size.height)/2; - self.textLabel.frame = CGRectMake(self.textLabel.frame.origin.x, self.textLabel.frame.origin.y+yOffset, self.textLabel.intrinsicContentSize.width, self.textLabel.frame.size.height); + self.textLabel.center = CGPointMake(self.textLabel.center.x, self.textLabel.center.y+yOffset); self.detailTextLabel.center = CGPointMake(self.detailTextLabel.center.x, self.detailTextLabel.center.y+yOffset); } } #pragma mark Customization -- (void)setMainColor:(UIColor *)mainColor { - _mainColor = mainColor; - self.textLabel.textColor = mainColor; -} - -- (void)setMainFont:(UIFont *)mainFont { - _mainFont = mainFont; - self.textLabel.font = mainFont; -} - -- (void)setSecondaryColor:(UIColor *)secondaryColor { - _secondaryColor = secondaryColor; - self.textLabel.highlightedTextColor = [UIColor whiteColor]; - self.detailTextLabel.textColor = secondaryColor; - self.detailTextLabel.highlightedTextColor = [UIColor whiteColor]; - self.tintColor = secondaryColor; -} - -- (void)setSecondaryFont:(UIFont *)secondaryFont { - _secondaryFont = secondaryFont; - self.detailTextLabel.font = secondaryFont; -} - -- (void)setSelectedColor:(UIColor *)selectedColor { - _selectedColor = selectedColor; +- (void)_updateAppearance { + self.tintColor = self.secondaryColor; + + self.textLabel.textColor = self.mainColor; + self.textLabel.font = self.mainFont; + + self.detailTextLabel.textColor = self.secondaryColor; + self.detailTextLabel.font = self.secondaryFont; + self.selectedBackgroundView = [UIView new]; - self.selectedBackgroundView.backgroundColor = selectedColor; + self.selectedBackgroundView.backgroundColor = self.selectedColor; } #pragma mark Subclassing @@ -69,7 +74,7 @@ - (void)setup {} - (void)setupConstraints {} - (void)updateAppearance {} - (CGFloat)expansionHeight {return 0;} -- (NSString *)footerTitle {return self.defaultFooterTitle;} +- (NSString *)footerTitle {return nil;} - (void)wasSelectedFromViewController:(BOTableViewController *)viewController {} - (void)settingValueDidChange {} diff --git a/Bohr/BOTableViewController.h b/Bohr/BOTableViewController.h index d59e651..9d6bcce 100644 --- a/Bohr/BOTableViewController.h +++ b/Bohr/BOTableViewController.h @@ -7,22 +7,17 @@ // #import +#import "BOTableViewSection.h" @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 array of BOTableViewSections of the controller. +@property (nonatomic, readonly) NSArray *sections; /// The setup method for the controller. - (void)setup; +/// Adds a new section to the controller. +- (void)addSection:(BOTableViewSection *)section; + @end diff --git a/Bohr/BOTableViewController.m b/Bohr/BOTableViewController.m index 6e62f04..c5fd617 100644 --- a/Bohr/BOTableViewController.m +++ b/Bohr/BOTableViewController.m @@ -9,29 +9,44 @@ #import "BOTableViewController.h" #import "BOTableViewController+Private.h" +#import "BOTableViewCell+Private.h" #import "BOTableViewCell+Subclass.h" #import "BOSetting+Private.h" @interface BOTableViewController () -@property (nonatomic, strong) NSArray *footerViews; +@property (nonatomic) NSArray *sections; +@property (nonatomic) NSArray *footerViews; @end @implementation BOTableViewController -- (void)awakeFromNib { - [self loadView]; - UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tableViewReceivedTap)]; - tapGestureRecognizer.cancelsTouchesInView = NO; - [self.tableView addGestureRecognizer:tapGestureRecognizer]; - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; - self.tableView.tableFooterView = [UIView new]; - [self setup]; +- (instancetype)init { + return [self initWithStyle:UITableViewStyleGrouped]; } -- (void)tableViewReceivedTap { - [self.tableView endEditing:YES]; +- (instancetype)initWithStyle:(UITableViewStyle)style { + if (self = [super initWithStyle:style]) { + self.sections = [NSArray new]; + + self.tableView.estimatedRowHeight = 55; + self.tableView.rowHeight = UITableViewAutomaticDimension; + self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag; + self.tableView.tableFooterView = [UIView new]; + + UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self.tableView action:@selector(endEditing:)]; + tapGestureRecognizer.cancelsTouchesInView = NO; + [self.tableView addGestureRecognizer:tapGestureRecognizer]; + + [self setup]; + } + + return self; +} + +- (void)addSection:(BOTableViewSection *)section { + self.sections = [self.sections arrayByAddingObject:section]; } // Apple pls http://blog.supertop.co/post/80781694515/viewmightappear @@ -52,69 +67,98 @@ - (void)viewWillAppear:(BOOL)animated { } } -#pragma mark Headers & cells +#pragma mark Headers & Cells -- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { - UITableViewHeaderFooterView *header = (UITableViewHeaderFooterView *)view; - - if (self.headerTitlesColor) header.textLabel.textColor = self.headerTitlesColor; - if (self.headerTitlesFont) header.textLabel.font = self.headerTitlesFont; +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)sectionIndex { + BOTableViewSection *section = self.sections[sectionIndex]; + return section.headerTitle; +} + +- (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UITableViewHeaderFooterView *)headerView forSection:(NSInteger)sectionIndex { + BOTableViewSection *section = self.sections[sectionIndex]; + if (section.headerTitleColor) headerView.textLabel.textColor = section.headerTitleColor; + if (section.headerTitleFont) headerView.textLabel.font = section.headerTitleFont; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return self.sections.count; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex { + BOTableViewSection *section = self.sections[sectionIndex]; + return section.cells.count; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - CGFloat rowHeight = MAX(self.tableView.rowHeight, [super tableView:tableView heightForRowAtIndexPath:indexPath]); - - BOTableViewCell *cell = (BOTableViewCell *)[self tableView:tableView cellForRowAtIndexPath:indexPath]; - if ([cell isKindOfClass:[BOTableViewCell class]]) { - return rowHeight + ([indexPath isEqual:self.expansionIndexPath] ? [cell expansionHeight] : 0); - } - - return rowHeight; + BOTableViewSection *section = self.sections[indexPath.section]; + BOTableViewCell *cell = section.cells[indexPath.row]; + CGFloat cellHeight = [cell systemLayoutSizeFittingSize:CGSizeMake(cell.contentView.frame.size.width, 0)].height; + + if (cellHeight < self.tableView.estimatedRowHeight) { + cellHeight = self.tableView.estimatedRowHeight; + } else { + cellHeight += 10; + } + + cell.layoutMargins = UIEdgeInsetsMake(cellHeight, cell.layoutMargins.left, cell.layoutMargins.bottom, cell.layoutMargins.right); + + if ([self.expansionIndexPath isEqual:indexPath]) { + cellHeight += [cell expansionHeight]; + } + + return cellHeight; } -- (void)tableView:(UITableView *)tableView willDisplayCell:(BOTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { - if ([cell isKindOfClass:[BOTableViewCell class]]) { - cell.indexPath = indexPath; - - if (cell.layoutMargins.top == 8) { - CGFloat cellHeight = [self tableView:tableView heightForRowAtIndexPath:indexPath]; - cell.layoutMargins = UIEdgeInsetsMake(cellHeight, cell.layoutMargins.left, cell.layoutMargins.bottom, cell.layoutMargins.right); - } - - if (cell.setting && !cell.setting.valueDidChangeBlock) { - __unsafe_unretained typeof(cell) _cell = cell; - __unsafe_unretained typeof(self) _self = self; +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + BOTableViewSection *section = self.sections[indexPath.section]; + BOTableViewCell *cell = section.cells[indexPath.row]; + cell.indexPath = indexPath; + + if (cell.setting && !cell.setting.valueDidChangeBlock) { + [UIView performWithoutAnimation:^{ + __unsafe_unretained typeof(self) weakSelf = self; + __unsafe_unretained typeof(cell) weakCell = cell; cell.setting.valueDidChangeBlock = ^{ - [_cell settingValueDidChange]; - [_self reloadTableView]; + [weakSelf reloadTableView]; + [weakCell settingValueDidChange]; }; - - [UIView performWithoutAnimation:^{ - [cell settingValueDidChange]; - }]; - } - - [cell updateAppearance]; + }]; } + + return cell; +} + +- (void)reloadTableView { + [UIView performWithoutAnimation:^{ + [self.tableView beginUpdates]; + [self.tableView endUpdates]; + }]; +} + +- (void)tableView:(UITableView *)tableView willDisplayCell:(BOTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { + [cell _updateAppearance]; + [cell updateAppearance]; } - (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.expansionIndexPath = ![indexPath isEqual:self.expansionIndexPath] ? indexPath : nil; - [self.tableView deselectRowAtIndexPath:cell.indexPath animated:NO]; + [self.tableView deselectRowAtIndexPath: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]; - } + [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; + } else if (cell.destinationViewController) { + [self.navigationController pushViewController:cell.destinationViewController animated:YES]; + } else if ([cell respondsToSelector:@selector(wasSelectedFromViewController:)]) { + [cell wasSelectedFromViewController:self]; } - if ([cell respondsToSelector:@selector(wasSelectedFromViewController:)]) [cell wasSelectedFromViewController:self]; + if (cell.accessoryType != UITableViewCellAccessoryDisclosureIndicator) { + [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; + } } #pragma mark Dynamic footers @@ -132,40 +176,31 @@ - (NSArray *)footerViews { return _footerViews; } -- (void)reloadTableView { - [UIView performWithoutAnimation:^{ - [self.tableView beginUpdates]; - [self.tableView endUpdates]; - }]; -} - - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { UITableViewHeaderFooterView *footerView = self.footerViews[section]; footerView.textLabel.text = [self tableView:tableView titleForFooterInSection:section]; - return [super tableView:tableView heightForFooterInSection:section]; + return footerView.intrinsicContentSize.height; } -- (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 = @""; +- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)sectionIndex { + + // First, we get the section value, and if it's nil we set it to an empty string (this is the lowest priority for dynamic footers). + BOTableViewSection *section = self.sections[sectionIndex]; + NSString *footerTitle = section.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]; + BOTableViewCell *lastCell = [section.cells lastObject]; + if ([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]]; - - if ([lastCell isKindOfClass:[BOTableViewCell class]] && cell.accessoryType == UITableViewCellAccessoryCheckmark) { + for (BOTableViewCell *cell in section.cells) { + if (cell.accessoryType == UITableViewCellAccessoryCheckmark) { footerTitle = [cell footerTitle]; } } - return footerTitle; + return footerTitle ? footerTitle : @""; } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { @@ -173,11 +208,10 @@ - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger return footerView; } -- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section { - UITableViewHeaderFooterView *footer = (UITableViewHeaderFooterView *)view; - - if (self.footerTitlesColor) footer.textLabel.textColor = self.footerTitlesColor; - if (self.footerTitlesFont) footer.textLabel.font = self.footerTitlesFont; +- (void)tableView:(UITableView *)tableView willDisplayFooterView:(UITableViewHeaderFooterView *)footerView forSection:(NSInteger)sectionIndex { + BOTableViewSection *section = self.sections[sectionIndex]; + if (section.footerTitleColor) footerView.textLabel.textColor = section.footerTitleColor; + if (section.footerTitleFont) footerView.textLabel.font = section.footerTitleFont; } #pragma mark Subclassing diff --git a/Bohr/BOTableViewSection.h b/Bohr/BOTableViewSection.h new file mode 100644 index 0000000..1cbdec3 --- /dev/null +++ b/Bohr/BOTableViewSection.h @@ -0,0 +1,46 @@ +// +// BOTableViewSection.h +// Bohr +// +// Created by David Román Aguirre on 26/08/15. +// +// + +#import +#import "BOTableViewCell.h" +#import "MZAppearance.h" + +@interface BOTableViewSection : NSObject + +/// The header title of the section. +@property (nonatomic) NSString *headerTitle; + +/// The header title color of the section. +@property (nonatomic) UIColor *headerTitleColor MZ_APPEARANCE_SELECTOR; + +/// The header title font of the section. +@property (nonatomic) UIFont *headerTitleFont MZ_APPEARANCE_SELECTOR; + +/// The footer title of the section. +@property (nonatomic) NSString *footerTitle; + +/// The footer title color of the section. +@property (nonatomic) UIColor *footerTitleColor MZ_APPEARANCE_SELECTOR; + +/// The footer title color of the section. +@property (nonatomic) UIFont *footerTitleFont MZ_APPEARANCE_SELECTOR; + +/// The cells for the section. +@property (nonatomic, readonly) NSArray *cells; + +/** Initializes a new BOTableViewSection object. + * + * @param headerTitle The section header title. + * @param handler A block passed in order to set up anything in the section. + **/ ++ (instancetype)sectionWithHeaderTitle:(NSString *)headerTitle handler:(void (^)(BOTableViewSection *section))handler; + +/// Adds a cell to the section. +- (void)addCell:(BOTableViewCell *)cell; + +@end diff --git a/Bohr/BOTableViewSection.m b/Bohr/BOTableViewSection.m new file mode 100644 index 0000000..6cf35a9 --- /dev/null +++ b/Bohr/BOTableViewSection.m @@ -0,0 +1,49 @@ +// +// BOTableViewSection.m +// Bohr +// +// Created by David Román Aguirre on 26/08/15. +// +// + +#import "BOTableViewSection.h" + +@interface BOTableViewSection () + +@property (nonatomic) NSArray *cells; + +@end + +@implementation BOTableViewSection + ++ (instancetype)appearance { + return [MZAppearance appearanceForClass:[self class]]; +} + +- (instancetype)init { + if (self = [super init]) { + self.cells = [NSArray new]; + [[[self class] appearance] applyInvocationTo:self]; + } + + return self; +} + +- (instancetype)initWithHeaderTitle:(NSString *)headerTitle handler:(void (^)(BOTableViewSection *))handler { + if (self = [self init]) { + self.headerTitle = headerTitle; + if (handler) handler(self); + } + + return self; +} + ++ (instancetype)sectionWithHeaderTitle:(NSString *)headerTitle handler:(void (^)(BOTableViewSection *))handler { + return [[self alloc] initWithHeaderTitle:headerTitle handler:handler]; +} + +- (void)addCell:(BOTableViewCell *)cell { + self.cells = [self.cells arrayByAddingObject:cell]; +} + +@end diff --git a/Bohr/BOTextTableViewCell.h b/Bohr/BOTextTableViewCell.h index fdbbbf3..6fc662a 100644 --- a/Bohr/BOTextTableViewCell.h +++ b/Bohr/BOTextTableViewCell.h @@ -24,10 +24,10 @@ typedef NS_ENUM(NSInteger, BOTextFieldInputError) { typedef void(^BOTextFieldInputErrorBlock)(BOTextTableViewCell *cell, BOTextFieldInputError error); /// The text field on the cell. -@property (nonatomic, strong) UITextField *textField; +@property (nonatomic) UITextField *textField; /// The minimum amount of non-blank characters necessary for the text field. -@property (nonatomic) IBInspectable NSInteger minimumTextLength; +@property (nonatomic) NSInteger minimumTextLength; /// A block defining an input error that has ocurred in the cell text field. @property (nonatomic, copy) BOTextFieldInputErrorBlock inputErrorBlock; diff --git a/Bohr/BOTextTableViewCell.m b/Bohr/BOTextTableViewCell.m index 13745b5..a7a0194 100644 --- a/Bohr/BOTextTableViewCell.m +++ b/Bohr/BOTextTableViewCell.m @@ -18,14 +18,8 @@ - (void)setup { self.textField.textAlignment = NSTextAlignmentRight; self.textField.returnKeyType = UIReturnKeyDone; self.textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; - [self.contentView addSubview:self.textField]; - - NSLayoutConstraint *centerYConstraint = [NSLayoutConstraint constraintWithItem:self.textField attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.textField.superview attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]; - NSLayoutConstraint *leftConstraint = [NSLayoutConstraint constraintWithItem:self.textField attribute:NSLayoutAttributeLeft relatedBy:NSLayoutRelationEqual toItem:self.textLabel attribute:NSLayoutAttributeRight multiplier:1 constant:15]; - NSLayoutConstraint *rightConstraint = [NSLayoutConstraint constraintWithItem:self.textField attribute:NSLayoutAttributeRight relatedBy:NSLayoutRelationEqual toItem:self.textField.superview attribute:NSLayoutAttributeRightMargin multiplier:1 constant:0]; - - self.textField.translatesAutoresizingMaskIntoConstraints = NO; - [self.textField.superview addConstraints:@[centerYConstraint, leftConstraint, rightConstraint]]; + self.textField.frame = CGRectMake(0, 0, 130, self.textField.intrinsicContentSize.height); + self.accessoryView = self.textField; } - (void)updateAppearance { diff --git a/Bohr/BOTimeTableViewCell.h b/Bohr/BOTimeTableViewCell.h index c2f50c9..122b4d0 100644 --- a/Bohr/BOTimeTableViewCell.h +++ b/Bohr/BOTimeTableViewCell.h @@ -11,6 +11,6 @@ @interface BOTimeTableViewCell : BOTableViewCell /// The minute interval showed on the time picker view. -@property (nonatomic) IBInspectable NSInteger minuteInterval; +@property (nonatomic) NSInteger minuteInterval; @end diff --git a/Bohr/BOTimeTableViewCell.m b/Bohr/BOTimeTableViewCell.m index c92b9b1..804050a 100644 --- a/Bohr/BOTimeTableViewCell.m +++ b/Bohr/BOTimeTableViewCell.m @@ -12,7 +12,7 @@ @interface BOTimeTableViewCell () -@property (nonatomic, strong) UIPickerView *timePickerView; +@property (nonatomic) UIPickerView *timePickerView; @end diff --git a/Bohr/Bohr.h b/Bohr/Bohr.h index 87d2adc..84c05a2 100644 --- a/Bohr/Bohr.h +++ b/Bohr/Bohr.h @@ -15,6 +15,7 @@ FOUNDATION_EXPORT double BohrVersionNumber; FOUNDATION_EXPORT const unsigned char BohrVersionString[]; #import +#import #import #import diff --git a/Bohr/Info.plist b/Bohr/Info.plist index c27b7c7..feea5cd 100644 --- a/Bohr/Info.plist +++ b/Bohr/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType FMWK CFBundleShortVersionString - 2.1.0 + 3.0.0 CFBundleSignature ???? CFBundleVersion diff --git a/Bohr/MZAppearance.h b/Bohr/MZAppearance.h new file mode 100755 index 0000000..6a6a4a2 --- /dev/null +++ b/Bohr/MZAppearance.h @@ -0,0 +1,55 @@ +// +// MZApperance.h +// MZAppearance +// +// Created by Michał Zaborowski on 17.08.2013. +// Copyright (c) 2013 Michał Zaborowski. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +#define MZ_APPEARANCE_SELECTOR UI_APPEARANCE_SELECTOR + +@protocol MZAppearance + +/** + To customize the appearance of all instances of a class, send the relevant appearance modification messages to the appearance proxy for the class. + */ ++ (instancetype)appearance; +@end + +@interface MZAppearance : NSObject + +/** + Applies the appearance of all instances to the object. + */ +- (void)applyInvocationTo:(id)target; + +/** + Applies the appearance of all instances to the object starting from the superclass + */ +- (void)applyInvocationRecursivelyTo:(id)target upToSuperClass:(Class)superClass; + +/** + Returns appearance for class + */ ++ (id)appearanceForClass:(Class)aClass; + +@end diff --git a/Bohr/MZAppearance.m b/Bohr/MZAppearance.m new file mode 100755 index 0000000..792f1bc --- /dev/null +++ b/Bohr/MZAppearance.m @@ -0,0 +1,111 @@ +// +// MZApperance.m +// MZAppearance +// +// Created by Michał Zaborowski on 17.08.2013. +// Copyright (c) 2013 Michał Zaborowski. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "MZAppearance.h" + +static NSMutableDictionary *instanceOfClassesDictionary = nil; + +@interface MZAppearance () +@property (strong, nonatomic) Class mainClass; +@property (strong, nonatomic) NSMutableArray *invocations; +@end + +@implementation MZAppearance + +- (id)initWithClass:(Class)thisClass +{ + _mainClass = thisClass; + _invocations = [NSMutableArray array]; + + return self; +} + +- (void)applyInvocationTo:(id)target +{ + for (NSInvocation *invocation in self.invocations) { + + // Create a new copy of the stored invocation, + // otherwise setting the new target, this will never be released + // because the invocation in the array is still alive after the call + + NSInvocation *targetInvocation = [invocation copy]; + [targetInvocation setTarget:target]; + [targetInvocation invoke]; + targetInvocation = nil; + } +} + +- (void)applyInvocationRecursivelyTo:(id)target upToSuperClass:(Class)superClass +{ + NSMutableArray *classes = [NSMutableArray array]; + + // We now need to first set the properties of the superclass + for (Class class = [target class]; + [class isSubclassOfClass:superClass] || class == superClass; + class = [class superclass]) { + [classes addObject:class]; + } + + NSEnumerator *reverseClasses = [classes reverseObjectEnumerator]; + + for (Class class in reverseClasses) { + [[MZAppearance appearanceForClass:class] applyInvocationTo:target]; + } +} + ++ (id)appearanceForClass:(Class)aClass +{ + static dispatch_once_t onceToken; + + dispatch_once(&onceToken, ^{ + instanceOfClassesDictionary = [[NSMutableDictionary alloc] init]; + }); + + if (![instanceOfClassesDictionary objectForKey:NSStringFromClass(aClass)]) + { + id appearance = [[self alloc] initWithClass:aClass]; + [instanceOfClassesDictionary setObject:appearance forKey:NSStringFromClass(aClass)]; + return appearance; + } + else { + return [instanceOfClassesDictionary objectForKey:NSStringFromClass(aClass)]; + } + +} + +- (void)forwardInvocation:(NSInvocation *)anInvocation; +{ + [anInvocation setTarget:nil]; + [anInvocation retainArguments]; + + [self.invocations addObject:anInvocation]; +} + +- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector +{ + return [self.mainClass instanceMethodSignatureForSelector:aSelector]; +} + +@end diff --git a/Bohr/NSInvocation+Copy.h b/Bohr/NSInvocation+Copy.h new file mode 100755 index 0000000..9e23625 --- /dev/null +++ b/Bohr/NSInvocation+Copy.h @@ -0,0 +1,32 @@ +// +// NSInvocation+Copy.h +// MZFormSheetControllerExample +// +// Created by Michał Zaborowski on 17.08.2013. +// Copyright (c) 2013 Michał Zaborowski. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import + +@interface NSInvocation (Copy) + +- (id)copy; + +@end diff --git a/Bohr/NSInvocation+Copy.m b/Bohr/NSInvocation+Copy.m new file mode 100755 index 0000000..5e0e935 --- /dev/null +++ b/Bohr/NSInvocation+Copy.m @@ -0,0 +1,216 @@ +// +// NSInvocation+Copy.m +// MZFormSheetControllerExample +// +// Created by Michał Zaborowski on 17.08.2013. +// Copyright (c) 2013 Michał Zaborowski. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#import "NSInvocation+Copy.h" +#import + +@interface NSString (Encoding) + +- (BOOL)mz_isFirstCharacterEqual:(NSString *)string; +- (BOOL)mz_isFirstCharacterCaseInsensitiveEqual:(NSString *)string; +- (NSString *)mz_stringByRemovingMethodEnodingQualifiers; + +@end + +@implementation NSString (Encoding) + +- (BOOL)mz_isFirstCharacterEqual:(NSString *)string +{ + if (self.length < 1 || string.length < 1) { + return NO; + } + return [[self substringToIndex:1] isEqualToString:[string substringToIndex:1]]; +} + +- (BOOL)mz_isFirstCharacterCaseInsensitiveEqual:(NSString *)string +{ + if (self.length < 1 || string.length < 1) { + return NO; + } + return [[self substringToIndex:1] caseInsensitiveCompare:[string substringToIndex:1]] == NSOrderedSame; +} + +- (NSString *)mz_stringByRemovingMethodEnodingQualifiers +{ + if ([self mz_isFirstCharacterCaseInsensitiveEqual:@"r"] || + [self mz_isFirstCharacterCaseInsensitiveEqual:@"n"] || + [self mz_isFirstCharacterCaseInsensitiveEqual:@"o"] || + [self mz_isFirstCharacterEqual:@"V"]) { + return [self substringFromIndex:1]; + } else { + return self; + } +} + +@end + +BOOL mz_areObjCTypesEqual(NSString *argmuentType, const char *encodingType) { + + NSString *encoding = [NSString stringWithUTF8String:encodingType]; + return [[argmuentType mz_stringByRemovingMethodEnodingQualifiers] isEqualToString:[encoding mz_stringByRemovingMethodEnodingQualifiers]]; +} + +@implementation NSInvocation (Copy) + +// http://stackoverflow.com/questions/15732885/uiappearance-proxy-for-custom-objects + +- (id)copy +{ + NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:self.methodSignature]; + NSUInteger numberOfArguments = [[self methodSignature] numberOfArguments]; + + [invocation setTarget:self.target]; + [invocation setSelector:self.selector]; + + if (numberOfArguments > 2) { + for (int i = 0; i < (numberOfArguments - 2); i++) { + NSInteger index = i+2; + + NSString *argumentType = [NSString stringWithUTF8String:[self.methodSignature getArgumentTypeAtIndex:index]]; + + if (mz_areObjCTypesEqual(argumentType, @encode(char))) { + char arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(unsigned char))) { + unsigned char arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(bool))) { + bool arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(short))) { + short arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(unsigned short))) { + unsigned short arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(int))) { + int arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(unsigned int))) { + unsigned int arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(long))) { + long arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(unsigned long))) { + unsigned long arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(long long))) { + long long arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(unsigned long long))) { + unsigned long long arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(float))) { + float arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(double))) { + double arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(id))) { + char buffer[sizeof(intmax_t)]; + [self getArgument:(void *)&buffer atIndex:i + 2]; + [invocation setArgument:(void *)&buffer atIndex:i + 2]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(SEL))) { + SEL arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(Class))) { + Class arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(char *))) { + char *arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(NSRange))) { + NSRange arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(CGPoint))) { + CGPoint arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(CGSize))) { + CGSize arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(CGColorRef))) { + CGColorRef arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if (mz_areObjCTypesEqual(argumentType, @encode(CGRect))) { + CGRect arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if ([argumentType mz_isFirstCharacterEqual:@"^"]) { + // generic pointer, including function pointers + + void *arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else if ([argumentType mz_isFirstCharacterEqual:@"@"]) { + // most likely a block, handle like a function pointer + + id arg; + [self getArgument:&arg atIndex:index]; + [invocation setArgument:&arg atIndex:index]; + } else { + + const char *argumentType = [self.methodSignature getArgumentTypeAtIndex:index]; + + NSUInteger argumentLength; + NSGetSizeAndAlignment(argumentType, &argumentLength, NULL); + + void *buffer = malloc(argumentLength); + + if (buffer) { + [self getArgument:buffer atIndex:index]; + [invocation setArgument:buffer atIndex:index]; + + free(buffer); + } + } + + } + } + + return invocation; +} + +@end diff --git a/BohrDemo/AppDelegate.m b/BohrDemo/AppDelegate.m index aaedadc..cc7ff5f 100644 --- a/BohrDemo/AppDelegate.m +++ b/BohrDemo/AppDelegate.m @@ -7,24 +7,21 @@ #import "AppDelegate.h" -#import +#import "TableViewController.h" +#import "UIColor+Bohr.h" @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - [self setupAppearance]; [self setupDefaults]; + [self setupAppearance]; - return YES; -} - -- (void)setupAppearance { - [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; + self.window = [UIWindow new]; + self.window.frame = [UIScreen mainScreen].bounds; + self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[TableViewController new]]; + [self.window makeKeyAndVisible]; - UIColor *blueColor = [UIColor colorWithRed:71/255.0 green:165/255.0 blue:254/255.0 alpha:1]; - [BOTableViewCell appearance].mainColor = [UIColor colorWithWhite:0.3 alpha:1]; - [BOTableViewCell appearance].secondaryColor = blueColor; - [BOTableViewCell appearance].selectedColor = blueColor; + return YES; } - (void)setupDefaults { @@ -32,10 +29,28 @@ - (void)setupDefaults { @"bool_1": @YES, @"bool_2": @NO, @"text": @"", - @"choice": @0, + @"choice_1": @0, @"choice_2": @2, @"time": @300, }]; } +- (void)setupAppearance { + [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; + + [UINavigationBar appearance].translucent = NO; + [UINavigationBar appearance].barTintColor = [UIColor bo_blueColor]; + [UINavigationBar appearance].tintColor = [UIColor whiteColor]; + [UINavigationBar appearance].titleTextAttributes = @{NSForegroundColorAttributeName: [UIColor whiteColor]}; + + [UITableView appearance].backgroundColor = [UIColor colorWithWhite:0.95 alpha:1]; + + [BOTableViewSection appearance].headerTitleColor = [UIColor bo_grayColor]; + [BOTableViewSection appearance].footerTitleColor = [UIColor bo_lightGrayColor]; + + [BOTableViewCell appearance].mainColor = [UIColor bo_darkGrayColor]; + [BOTableViewCell appearance].secondaryColor = [UIColor bo_blueColor]; + [BOTableViewCell appearance].selectedColor = [UIColor bo_blueColor]; +} + @end diff --git a/BohrDemo/Info.plist b/BohrDemo/Info.plist index e76f258..ba66b52 100644 --- a/BohrDemo/Info.plist +++ b/BohrDemo/Info.plist @@ -15,7 +15,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - 2.1.0 + 3.0.0 CFBundleSignature ???? CFBundleVersion @@ -24,8 +24,6 @@ UILaunchStoryboardName LaunchScreen - UIMainStoryboardFile - Main UIRequiredDeviceCapabilities armv7 diff --git a/BohrDemo/Main.storyboard b/BohrDemo/Main.storyboard deleted file mode 100644 index ae4f2f6..0000000 --- a/BohrDemo/Main.storyboard +++ /dev/null @@ -1,375 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/BohrDemo/OptionsTableViewController.h b/BohrDemo/OptionsTableViewController.h new file mode 100644 index 0000000..e1a7b83 --- /dev/null +++ b/BohrDemo/OptionsTableViewController.h @@ -0,0 +1,13 @@ +// +// OptionsTableViewController.h +// Bohr +// +// Created by David Román Aguirre on 28/08/15. +// +// + +#import + +@interface OptionsTableViewController : BOTableViewController + +@end diff --git a/BohrDemo/OptionsTableViewController.m b/BohrDemo/OptionsTableViewController.m new file mode 100644 index 0000000..ac799f0 --- /dev/null +++ b/BohrDemo/OptionsTableViewController.m @@ -0,0 +1,36 @@ +// +// OptionsTableViewController.m +// Bohr +// +// Created by David Román Aguirre on 28/08/15. +// +// + +#import "OptionsTableViewController.h" + +@implementation OptionsTableViewController + +- (void)setup { + + self.title = @"Choice options"; + + [self addSection:[BOTableViewSection sectionWithHeaderTitle:nil handler:^(BOTableViewSection *section) { + [section addCell:[BOOptionTableViewCell cellWithTitle:@"Some description for option 1" key:@"choice_2" handler:^(BOOptionTableViewCell *cell) { + cell.footerTitle = @"Some footer for option 1"; + }]]; + + [section addCell:[BOOptionTableViewCell cellWithTitle:@"Some description for option 2" key:@"choice_2" handler:^(BOOptionTableViewCell *cell) { + cell.footerTitle = @"Some footer for option 2"; + }]]; + + [section addCell:[BOOptionTableViewCell cellWithTitle:@"Some description for option 3" key:@"choice_2" handler:^(BOOptionTableViewCell *cell) { + cell.footerTitle = @"Some footer for option 3"; + }]]; + + [section addCell:[BOOptionTableViewCell cellWithTitle:@"Some description for option 4" key:@"choice_2" handler:^(BOOptionTableViewCell *cell) { + cell.footerTitle = @"Some footer for option 4"; + }]]; + }]]; +} + +@end diff --git a/BohrDemo/TableViewController.h b/BohrDemo/TableViewController.h index 6c37099..2879fd6 100644 --- a/BohrDemo/TableViewController.h +++ b/BohrDemo/TableViewController.h @@ -9,10 +9,5 @@ @interface TableViewController : BOTableViewController -@property (weak, nonatomic) IBOutlet BOTextTableViewCell *textCell; -@property (weak, nonatomic) IBOutlet BOChoiceTableViewCell *choiceCell; -@property (weak, nonatomic) IBOutlet BOChoiceTableViewCell *choiceDisclosureCell; -@property (weak, nonatomic) IBOutlet BOButtonTableViewCell *buttonCell; - @end diff --git a/BohrDemo/TableViewController.m b/BohrDemo/TableViewController.m index 7fc2a5c..aac304b 100644 --- a/BohrDemo/TableViewController.m +++ b/BohrDemo/TableViewController.m @@ -6,16 +6,55 @@ // #import "TableViewController.h" +#import "OptionsTableViewController.h" @implementation TableViewController - (void)setup { - self.textCell.textField.placeholder = @"Placeholder"; - self.textCell.inputErrorBlock = [self textFieldInputErrorBlock]; - self.choiceCell.options = @[@"Option 1", @"Option 2", @"Option 3"]; - self.choiceDisclosureCell.options = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4"]; - [self.buttonCell setTarget:self action:@selector(showButtonAlert)]; - self.buttonCell.defaultFooterTitle = @"Static footer set programatically"; + + self.title = @"Bohr"; + + [self addSection:[BOTableViewSection sectionWithHeaderTitle:@"Section 1" handler:^(BOTableViewSection *section) { + [section addCell:[BOSwitchTableViewCell cellWithTitle:@"Switch 1" key:@"bool_1" handler:nil]]; + [section addCell:[BOSwitchTableViewCell cellWithTitle:@"Switch 2" key:@"bool_2" handler:^(BOSwitchTableViewCell *cell) { + cell.onFooterTitle = @"Switch setting 2 is on"; + cell.offFooterTitle = @"Switch setting 2 is off"; + }]]; + }]]; + + __unsafe_unretained typeof(self) weakSelf = self; + [self addSection:[BOTableViewSection sectionWithHeaderTitle:@"Section 2" handler:^(BOTableViewSection *section) { + [section addCell:[BOTextTableViewCell cellWithTitle:@"Text" key:@"text" handler:^(BOTextTableViewCell *cell) { + cell.textField.placeholder = @"Placeholder"; + cell.inputErrorBlock = ^(BOTextTableViewCell *cell, BOTextFieldInputError error) { + [weakSelf presentAlertControllerWithTitle:@"Error" message:@"The text is too short"]; + }; + }]]; + + [section addCell:[BOTimeTableViewCell cellWithTitle:@"Time" key:@"time" handler:^(BOTimeTableViewCell *cell) { + cell.minuteInterval = 5; + }]]; + + [section addCell:[BOChoiceTableViewCell cellWithTitle:@"Choice" key:@"choice_1" handler:^(BOChoiceTableViewCell *cell) { + cell.options = @[@"Option 1", @"Option 2", @"Option 3"]; + cell.footerTitles = @[@"Option 1", @"Option 2", @"Option 3"]; + }]]; + + [section addCell:[BOChoiceTableViewCell cellWithTitle:@"Choice disclosure" key:@"choice_2" handler:^(BOChoiceTableViewCell *cell) { + cell.options = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4"]; + cell.destinationViewController = [OptionsTableViewController new]; + }]]; + }]]; + + [self addSection:[BOTableViewSection sectionWithHeaderTitle:@"Section 3" handler:^(BOTableViewSection *section) { + [section addCell:[BOButtonTableViewCell cellWithTitle:@"Button" key:nil handler:^(BOButtonTableViewCell *cell) { + cell.actionBlock = ^{ + [weakSelf showButtonAlert]; + }; + }]]; + + section.footerTitle = @"Static footer title"; + }]]; } - (void)presentAlertControllerWithTitle:(NSString *)title message:(NSString *)message { @@ -23,15 +62,8 @@ - (void)presentAlertControllerWithTitle:(NSString *)title message:(NSString *)me [alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:^(UIAlertAction *action) { [alertController dismissViewControllerAnimated:YES completion:nil]; }]]; - [self presentViewController:alertController animated:YES completion:nil]; -} - -- (BOTextFieldInputErrorBlock)textFieldInputErrorBlock { - __unsafe_unretained typeof(self) weakSelf = self; - return ^(BOTextTableViewCell *cell, BOTextFieldInputError error) { - [weakSelf presentAlertControllerWithTitle:@"Error" message:@"The text is too short"]; - }; + [self presentViewController:alertController animated:YES completion:nil]; } - (void)showButtonAlert { diff --git a/BohrDemo/UIColor+Bohr.h b/BohrDemo/UIColor+Bohr.h new file mode 100644 index 0000000..d8cc013 --- /dev/null +++ b/BohrDemo/UIColor+Bohr.h @@ -0,0 +1,19 @@ +// +// UIColor+Bohr.h +// Bohr +// +// Created by David Román Aguirre on 26/08/15. +// +// + +#import + +@interface UIColor (Bohr) + ++ (UIColor *)bo_lightGrayColor; ++ (UIColor *)bo_grayColor; ++ (UIColor *)bo_darkGrayColor; + ++ (UIColor *)bo_blueColor; + +@end diff --git a/BohrDemo/UIColor+Bohr.m b/BohrDemo/UIColor+Bohr.m new file mode 100644 index 0000000..6772bfc --- /dev/null +++ b/BohrDemo/UIColor+Bohr.m @@ -0,0 +1,29 @@ +// +// UIColor+Bohr.m +// Bohr +// +// Created by David Román Aguirre on 26/08/15. +// +// + +#import "UIColor+Bohr.h" + +@implementation UIColor (Bohr) + ++ (UIColor *)bo_lightGrayColor { + return [UIColor colorWithWhite:0.6 alpha:1]; +} + ++ (UIColor *)bo_grayColor { + return [UIColor colorWithWhite:0.5 alpha:1]; +} + ++ (UIColor *)bo_darkGrayColor { + return [UIColor colorWithWhite:0.3 alpha:1]; +} + ++ (UIColor *)bo_blueColor { + return [UIColor colorWithRed:71/255.0 green:165/255.0 blue:254/255.0 alpha:1]; +} + +@end