From b4cc76808f87b1dadab8877aa61b2c38c0b0cf5a Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 09:17:06 -0500 Subject: [PATCH 01/44] Refactor pull request #13 --- RETableViewManager/RETableViewCell.m | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/RETableViewManager/RETableViewCell.m b/RETableViewManager/RETableViewCell.m index 9ad62a3..690c1f5 100644 --- a/RETableViewManager/RETableViewCell.m +++ b/RETableViewManager/RETableViewCell.m @@ -46,7 +46,7 @@ #pragma mark - UI --(void)_addBackgroundImage +- (void)addBackgroundImage { self.tableViewManager.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.backgroundView = [[UIView alloc] initWithFrame:self.contentView.bounds]; @@ -56,7 +56,7 @@ [self.backgroundView addSubview:_backgroundImageView]; } --(void)_addSelectedBackgroundImage +- (void)addSelectedBackgroundImage { self.selectedBackgroundView = [[UIView alloc] initWithFrame:self.contentView.bounds]; self.selectedBackgroundView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; @@ -75,11 +75,11 @@ self.selectionStyle = self.tableViewManager.style.defaultCellSelectionStyle; if ([self.tableViewManager.style hasCustomBackgroundImage]) { - [self _addBackgroundImage]; + [self addBackgroundImage]; } if ([self.tableViewManager.style hasCustomSelectedBackgroundImage]) { - [self _addSelectedBackgroundImage]; + [self addSelectedBackgroundImage]; } } @@ -132,15 +132,15 @@ if ([self.section.style hasCustomBackgroundImage]) { self.backgroundColor = [UIColor clearColor]; - if (_backgroundImageView==nil) { - [self _addBackgroundImage]; + if (!_backgroundImageView) { + [self addBackgroundImage]; } _backgroundImageView.image = [self.section.style backgroundImageForCellType:self.type]; } if ([self.section.style hasCustomSelectedBackgroundImage]) { - if (_selectedBackgroundImageView==nil) { - [self _addSelectedBackgroundImage]; + if (!_selectedBackgroundImageView) { + [self addSelectedBackgroundImage]; } _selectedBackgroundImageView.image = [self.section.style selectedBackgroundImageForCellType:self.type]; } From cc2cfe3ab8f0ea942b764e8735da27201a825ece Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 09:27:30 -0500 Subject: [PATCH 02/44] Automatically register XIBs if it exists for the matching cell name --- RETableViewManager/RETableViewManager.m | 6 ++++++ .../Classes/Controllers/XIBTestViewController.m | 4 ---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 7096c19..064a6d6 100644 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -104,6 +104,12 @@ BOOL REDeviceIsUIKit7() { NSAssert(NSClassFromString(objectClass), ([NSString stringWithFormat:@"Item class '%@' does not exist.", identifier])); NSAssert(NSClassFromString(identifier), ([NSString stringWithFormat:@"Cell class '%@' does not exist.", identifier])); [_registeredClasses setObject:identifier forKey:objectClass]; + + // Perform check if a XIB exists with the same name as the cell class + // + if ([[NSBundle mainBundle] pathForResource:identifier ofType:@"nib"]) { + [self.tableView registerNib:[UINib nibWithNibName:identifier bundle:nil] forCellReuseIdentifier:objectClass]; + } } - (id)objectAtKeyedSubscript:(id )key diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m index 428ef36..1801718 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m @@ -24,10 +24,6 @@ // _manager = [[RETableViewManager alloc] initWithTableView:self.tableView delegate:self]; - // Register XIB file - // - [self.tableView registerNib:[UINib nibWithNibName:@"XIBTestCell" bundle:nil] forCellReuseIdentifier:@"XIBTestItem"]; - // Map item to a cell // _manager[@"XIBTestItem"] = @"XIBTestCell"; From 97b93561de7df7ee1e3256617171d4fb5ad1a7b0 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 09:28:50 -0500 Subject: [PATCH 03/44] Add comment --- .../Classes/Controllers/XIBTestViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m index 1801718..8b84fad 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m @@ -24,7 +24,7 @@ // _manager = [[RETableViewManager alloc] initWithTableView:self.tableView delegate:self]; - // Map item to a cell + // Map item to a cell, this will also register the XIBTestCell.xib for the XIBTestItem identifier // _manager[@"XIBTestItem"] = @"XIBTestCell"; From 658bcbaa2aa08950fc7a1d8a92f4672293f25424 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:08:47 -0500 Subject: [PATCH 04/44] Simplify XIB loading API --- RETableViewManager/RETableViewManager.m | 19 +++++++++++++++++-- .../Controllers/XIBTestViewController.m | 1 - 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 064a6d6..7ebefa7 100644 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -43,6 +43,15 @@ BOOL REDeviceIsUIKit7() { return NO; } +@interface RETableViewManager () + +/** + The array of pairs of items / cell classes. + */ +@property (strong, readwrite, nonatomic) NSMutableDictionary *registeredXIBs; + +@end + @implementation RETableViewManager - (id)init @@ -75,6 +84,7 @@ BOOL REDeviceIsUIKit7() { _sections = [[NSMutableArray alloc] init]; _registeredClasses = [[NSMutableDictionary alloc] init]; + _registeredXIBs = [[NSMutableDictionary alloc] init]; _style = [[RETableViewCellStyle alloc] init]; [self registerDefaultClasses]; @@ -103,11 +113,12 @@ BOOL REDeviceIsUIKit7() { { NSAssert(NSClassFromString(objectClass), ([NSString stringWithFormat:@"Item class '%@' does not exist.", identifier])); NSAssert(NSClassFromString(identifier), ([NSString stringWithFormat:@"Cell class '%@' does not exist.", identifier])); - [_registeredClasses setObject:identifier forKey:objectClass]; + self.registeredClasses[objectClass] = identifier; // Perform check if a XIB exists with the same name as the cell class // if ([[NSBundle mainBundle] pathForResource:identifier ofType:@"nib"]) { + self.registeredXIBs[identifier] = objectClass; [self.tableView registerNib:[UINib nibWithNibName:identifier bundle:nil] forCellReuseIdentifier:objectClass]; } } @@ -160,9 +171,13 @@ BOOL REDeviceIsUIKit7() { cellStyle = ((RETableViewItem *)item).style; NSString *cellIdentifier = [item respondsToSelector:@selector(cellIdentifier)] && item.cellIdentifier ? item.cellIdentifier : [NSString stringWithFormat:@"RETableViewManager_%@_%i", [item class], cellStyle]; - + Class cellClass = [self classForCellAtIndexPath:indexPath]; + if (self.registeredXIBs[NSStringFromClass(cellClass)]) { + cellIdentifier = self.registeredXIBs[NSStringFromClass(cellClass)]; + } + RETableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[cellClass alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier]; diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m index 8b84fad..2b69b9e 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m @@ -40,7 +40,6 @@ selectionHandler:^(RETableViewItem *item) { [item deselectRowAnimated:YES]; }]; - item.cellIdentifier = @"XIBTestItem"; [section addItem:item]; } } From ed2373f4564007d23973933e4c5b79801da37dfa Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:13:17 -0500 Subject: [PATCH 05/44] XIB identifier fixes --- RETableViewManager/RETableViewManager.m | 6 +++++- .../Classes/Controllers/XIBTestViewController.m | 8 ++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 7ebefa7..778cc69 100644 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -170,7 +170,7 @@ BOOL REDeviceIsUIKit7() { if ([item isKindOfClass:[RETableViewItem class]]) cellStyle = ((RETableViewItem *)item).style; - NSString *cellIdentifier = [item respondsToSelector:@selector(cellIdentifier)] && item.cellIdentifier ? item.cellIdentifier : [NSString stringWithFormat:@"RETableViewManager_%@_%i", [item class], cellStyle]; + NSString *cellIdentifier = [NSString stringWithFormat:@"RETableViewManager_%@_%i", [item class], cellStyle]; Class cellClass = [self classForCellAtIndexPath:indexPath]; @@ -178,6 +178,10 @@ BOOL REDeviceIsUIKit7() { cellIdentifier = self.registeredXIBs[NSStringFromClass(cellClass)]; } + if ([item respondsToSelector:@selector(cellIdentifier)] && item.cellIdentifier) { + cellIdentifier = item.cellIdentifier; + } + RETableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; if (cell == nil) { cell = [[cellClass alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier]; diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m index 2b69b9e..57461f1 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/XIBTestViewController.m @@ -42,6 +42,14 @@ }]; [section addItem:item]; } + + // Cell is being assigned an automatic identifier + // + // You can manually set it if you want to: + // item.cellIdentifier = @"CustomIdentifier"; + // + // You'll need to register a cell class for it as well: + // [self.tableView registerNib:[UINib nibWithNibName:@"XIBTestCell" bundle:nil] forCellReuseIdentifier:@"CustomIdentifier"]; } @end From 958419cd2876c0bd888c7019116dda09a292b9cc Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:19:13 -0500 Subject: [PATCH 06/44] Update readme --- README.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/README.md b/README.md index 203de7a..f4b1c92 100644 --- a/README.md +++ b/README.md @@ -455,6 +455,17 @@ Quick example: } ``` +### Interface Builder Support + +Interface builder cells are supported out of the box, no special set up needed. +Cells and items are being automatically registered, e.g. + +```objective-c +_manager[@"XIBTestItem"] = @"XIBTestCell"; +``` + +Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` file in your bundle. That's it. + ### Styling It's super easy to customize different offsets and cell background images of From 7c11b0188ff1354fed46b97f2ab1ae4869b4d54c Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:20:09 -0500 Subject: [PATCH 07/44] Add comments --- .../Classes/Controllers/IndexedListViewController.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/IndexedListViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/IndexedListViewController.m index 13fceac..5d57327 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/IndexedListViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/IndexedListViewController.m @@ -32,6 +32,8 @@ RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:sectionTitle]; section.indexTitle = sectionTitle; // assign index title + // Add 5 items with name `section title + item index` + // for (NSInteger i = 1; i <= 5; i++) [section addItem:[NSString stringWithFormat:@"%@%i", sectionTitle, i]]; From 42e29a4ee8c04254548b4d23c7ded4ff736e926e Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:21:16 -0500 Subject: [PATCH 08/44] Update readme --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f4b1c92..627076e 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.1.2' +pod 'RETableViewManager', '~> 1.1.3' ``` Install into your Xcode project: @@ -458,13 +458,13 @@ Quick example: ### Interface Builder Support Interface builder cells are supported out of the box, no special set up needed. -Cells and items are being automatically registered, e.g. +Cells and items are being automatically registered like any other custom cell in `RETableViewManager`: ```objective-c _manager[@"XIBTestItem"] = @"XIBTestCell"; ``` -Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` file in your bundle. That's it. +Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` fileg in your bundle. That's it. ### Styling From 9b0ee05251389065918735f9fc88ee1de21614b2 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:21:44 -0500 Subject: [PATCH 09/44] Typo fix --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 627076e..6867d61 100644 --- a/README.md +++ b/README.md @@ -464,7 +464,7 @@ Cells and items are being automatically registered like any other custom cell in _manager[@"XIBTestItem"] = @"XIBTestCell"; ``` -Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` fileg in your bundle. That's it. +Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` file in your bundle. That's it. ### Styling From a05fa4f2e2274d87194921d01246245f3c83e6e8 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:38:09 -0500 Subject: [PATCH 10/44] Fix UITextView placeholder alignment --- RETableViewManager/REPlaceholderTextView.m | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/RETableViewManager/REPlaceholderTextView.m b/RETableViewManager/REPlaceholderTextView.m index 97bcb98..dae1128 100644 --- a/RETableViewManager/REPlaceholderTextView.m +++ b/RETableViewManager/REPlaceholderTextView.m @@ -83,8 +83,12 @@ [self addSubview:_placeholderLabel]; } + _placeholderLabel.textAlignment = self.textAlignment; _placeholderLabel.text = self.placeholder; [_placeholderLabel sizeToFit]; + CGRect frame = _placeholderLabel.frame; + frame.size.width = self.bounds.size.width - self.frame.origin.x * 2; + _placeholderLabel.frame = frame; [self sendSubviewToBack:_placeholderLabel]; } From cb7768f9c2131d6f03d09ab0e363d70cdb04e2be Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 10:39:03 -0500 Subject: [PATCH 11/44] Version bump (1.1.3) --- RETableViewManager.podspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index 30c8175..fc416e9 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.1.2' + s.version = '1.1.3' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.1.2' } + :tag => '1.1.3' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' From 621f2326c1ad2d3069c8305ac52c02507889a50b Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 21 Aug 2013 16:58:54 -0500 Subject: [PATCH 12/44] Add REValidation --- RETableViewManager/Items/RETextItem.m | 8 + RETableViewManager/RETableViewItem.h | 7 + RETableViewManager/RETableViewManager.h | 1 + RETableViewManager/RETableViewManager.m | 6 + .../project.pbxproj | 52 +++++++ .../REValidation/NSError+REValidation.h | 32 ++++ .../REValidation/NSError+REValidation.m | 40 +++++ .../Vendor/REValidation/REValidation.h | 46 ++++++ .../Vendor/REValidation/REValidation.m | 141 ++++++++++++++++++ .../Vendor/REValidation/REValidator.h | 39 +++++ .../Vendor/REValidation/REValidator.m | 64 ++++++++ .../Validators/REEmailValidator.h | 30 ++++ .../Validators/REEmailValidator.m | 48 ++++++ .../Validators/RELengthValidator.h | 30 ++++ .../Validators/RELengthValidator.m | 68 +++++++++ .../Validators/REPresenceValidator.h | 30 ++++ .../Validators/REPresenceValidator.m | 44 ++++++ 17 files changed, 686 insertions(+) create mode 100644 RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.m create mode 100644 RETableViewManagerExample/Vendor/REValidation/REValidation.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/REValidation.m create mode 100644 RETableViewManagerExample/Vendor/REValidation/REValidator.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/REValidator.m create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.m diff --git a/RETableViewManager/Items/RETextItem.m b/RETableViewManager/Items/RETextItem.m index 965b721..8a5f9f5 100644 --- a/RETableViewManager/Items/RETextItem.m +++ b/RETableViewManager/Items/RETextItem.m @@ -55,4 +55,12 @@ return self; } +#pragma mark - +#pragma mark Error validation + +- (NSArray *)errors +{ + return [REValidation validateObject:self.value name:self.name ? self.name : self.title validators:self.validators]; +} + @end diff --git a/RETableViewManager/RETableViewItem.h b/RETableViewManager/RETableViewItem.h index 869e343..5d391ab 100644 --- a/RETableViewManager/RETableViewItem.h +++ b/RETableViewManager/RETableViewItem.h @@ -25,6 +25,7 @@ #import #import "RETableViewCellStyle.h" +#import "REValidation.h" @class RETableViewSection; @@ -54,6 +55,12 @@ @property (assign, readwrite, nonatomic) CGFloat cellHeight; @property (copy, readwrite, nonatomic) NSString *cellIdentifier; +// Error validation +// +@property (copy, readwrite, nonatomic) NSString *name; +@property (strong, readwrite, nonatomic) NSArray *validators; +@property (strong, readonly, nonatomic) NSArray *errors; + + (instancetype)item; + (instancetype)itemWithTitle:(NSString *)title; + (instancetype)itemWithTitle:(NSString *)title accessoryType:(UITableViewCellAccessoryType)accessoryType selectionHandler:(void(^)(RETableViewItem *item))selectionHandler; diff --git a/RETableViewManager/RETableViewManager.h b/RETableViewManager/RETableViewManager.h index e1ff3ef..98f7e59 100644 --- a/RETableViewManager/RETableViewManager.h +++ b/RETableViewManager/RETableViewManager.h @@ -44,6 +44,7 @@ #import "REFloatItem.h" #import "REDateTimeItem.h" #import "REMultipleChoiceItem.h" +#import "REValidation.h" @protocol RETableViewManagerDelegate; diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 778cc69..9b192f5 100644 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -54,6 +54,12 @@ BOOL REDeviceIsUIKit7() { @implementation RETableViewManager ++ (void)initialize +{ + [REValidation registerDefaultValidators]; + [REValidation registerDefaultErrorMessages]; +} + - (id)init { @throw [NSException exceptionWithName:NSGenericException reason:@"init not supported, use initWithTableView: instead." userInfo:nil]; diff --git a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj index bebcb30..83e5782 100644 --- a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj +++ b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj @@ -39,6 +39,12 @@ 30939CF317949A10004D95A9 /* userpic5.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 30939CE717949A10004D95A9 /* userpic5.jpg */; }; 30939CF417949A10004D95A9 /* userpic6.jpg in Resources */ = {isa = PBXBuildFile; fileRef = 30939CE817949A10004D95A9 /* userpic6.jpg */; }; 30939CF917949B2D004D95A9 /* REFormattedNumberField.m in Sources */ = {isa = PBXBuildFile; fileRef = 30939CF817949B2D004D95A9 /* REFormattedNumberField.m */; }; + 30B00D5E17C56EEF0010D439 /* NSError+REValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5217C56EEF0010D439 /* NSError+REValidation.m */; }; + 30B00D5F17C56EEF0010D439 /* REValidation.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5417C56EEF0010D439 /* REValidation.m */; }; + 30B00D6017C56EEF0010D439 /* REValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5617C56EEF0010D439 /* REValidator.m */; }; + 30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5917C56EEF0010D439 /* REEmailValidator.m */; }; + 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */; }; + 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */; }; 30D1C7D617AC08F4001F731C /* First_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */; }; 30D1C7D717AC08F4001F731C /* Last_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */; }; 30D1C7D817AC08F4001F731C /* Middle_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */; }; @@ -135,6 +141,18 @@ 30939CE817949A10004D95A9 /* userpic6.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = userpic6.jpg; sourceTree = ""; }; 30939CF717949B2D004D95A9 /* REFormattedNumberField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REFormattedNumberField.h; sourceTree = ""; }; 30939CF817949B2D004D95A9 /* REFormattedNumberField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REFormattedNumberField.m; sourceTree = ""; }; + 30B00D5117C56EEF0010D439 /* NSError+REValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSError+REValidation.h"; sourceTree = ""; }; + 30B00D5217C56EEF0010D439 /* NSError+REValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSError+REValidation.m"; sourceTree = ""; }; + 30B00D5317C56EEF0010D439 /* REValidation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REValidation.h; sourceTree = ""; }; + 30B00D5417C56EEF0010D439 /* REValidation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REValidation.m; sourceTree = ""; }; + 30B00D5517C56EEF0010D439 /* REValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REValidator.h; sourceTree = ""; }; + 30B00D5617C56EEF0010D439 /* REValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REValidator.m; sourceTree = ""; }; + 30B00D5817C56EEF0010D439 /* REEmailValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REEmailValidator.h; sourceTree = ""; }; + 30B00D5917C56EEF0010D439 /* REEmailValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REEmailValidator.m; sourceTree = ""; }; + 30B00D5A17C56EEF0010D439 /* RELengthValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RELengthValidator.h; sourceTree = ""; }; + 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RELengthValidator.m; sourceTree = ""; }; + 30B00D5C17C56EEF0010D439 /* REPresenceValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REPresenceValidator.h; sourceTree = ""; }; + 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REPresenceValidator.m; sourceTree = ""; }; 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "First_Alt@2x.png"; path = "Resources/First_Alt@2x.png"; sourceTree = ""; }; 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Last_Alt@2x.png"; path = "Resources/Last_Alt@2x.png"; sourceTree = ""; }; 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Middle_Alt@2x.png"; path = "Resources/Middle_Alt@2x.png"; sourceTree = ""; }; @@ -301,6 +319,7 @@ 30939CF517949B2D004D95A9 /* Vendor */ = { isa = PBXGroup; children = ( + 30B00D5017C56EEF0010D439 /* REValidation */, 30939CF617949B2D004D95A9 /* REFormattedNumberField */, ); path = Vendor; @@ -315,6 +334,33 @@ path = REFormattedNumberField; sourceTree = ""; }; + 30B00D5017C56EEF0010D439 /* REValidation */ = { + isa = PBXGroup; + children = ( + 30B00D5117C56EEF0010D439 /* NSError+REValidation.h */, + 30B00D5217C56EEF0010D439 /* NSError+REValidation.m */, + 30B00D5317C56EEF0010D439 /* REValidation.h */, + 30B00D5417C56EEF0010D439 /* REValidation.m */, + 30B00D5517C56EEF0010D439 /* REValidator.h */, + 30B00D5617C56EEF0010D439 /* REValidator.m */, + 30B00D5717C56EEF0010D439 /* Validators */, + ); + path = REValidation; + sourceTree = ""; + }; + 30B00D5717C56EEF0010D439 /* Validators */ = { + isa = PBXGroup; + children = ( + 30B00D5817C56EEF0010D439 /* REEmailValidator.h */, + 30B00D5917C56EEF0010D439 /* REEmailValidator.m */, + 30B00D5A17C56EEF0010D439 /* RELengthValidator.h */, + 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */, + 30B00D5C17C56EEF0010D439 /* REPresenceValidator.h */, + 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */, + ); + path = Validators; + sourceTree = ""; + }; 30DB064616E934AD006C9530 /* RETableViewManager */ = { isa = PBXGroup; children = ( @@ -593,6 +639,12 @@ 303D966B17B7CCF800A418F3 /* XIBTestCell.m in Sources */, 303D967217B7CDE300A418F3 /* XIBTestViewController.m in Sources */, 30E5F50C17BBD163005CF1FE /* IndexedListViewController.m in Sources */, + 30B00D5E17C56EEF0010D439 /* NSError+REValidation.m in Sources */, + 30B00D5F17C56EEF0010D439 /* REValidation.m in Sources */, + 30B00D6017C56EEF0010D439 /* REValidator.m in Sources */, + 30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */, + 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */, + 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.h b/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.h new file mode 100644 index 0000000..86dfaf6 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.h @@ -0,0 +1,32 @@ +// +// NSError+REValidation.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 NSError (REValidation) + ++ (NSError *)re_validationErrorForDomain:(NSString *)domain, ...; + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.m b/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.m new file mode 100644 index 0000000..2e8f3c0 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/NSError+REValidation.m @@ -0,0 +1,40 @@ +// +// NSError+REValidation.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "NSError+REValidation.h" +#import "REValidation.h" + +@implementation NSError (REValidation) + ++ (NSError *)re_validationErrorForDomain:(NSString *)domain, ... +{ + va_list args; + va_start(args, domain); + NSError *error = [NSError errorWithDomain:domain code:0 userInfo:@{ NSLocalizedDescriptionKey:[[NSString alloc] initWithFormat:[REValidation errorMessageForDomain:domain] arguments:args] }]; + va_end(args); + return error; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.h b/RETableViewManagerExample/Vendor/REValidation/REValidation.h new file mode 100644 index 0000000..9614ac3 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.h @@ -0,0 +1,46 @@ +// +// REValidation.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 +#import "REValidator.h" +#import "NSError+REValidation.h" +#import "REPresenceValidator.h" +#import "RELengthValidator.h" +#import "REEmailValidator.h" + +@interface REValidation : NSObject + ++ (instancetype)sharedObject; ++ (void)registerDefaultValidators; ++ (void)registerDefaultErrorMessages; ++ (void)registerValidator:(Class)validatorClass; ++ (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string; ++ (NSError *)validateObject:(NSObject *)object name:(NSString *)name validator:(REValidator *)validator; ++ (NSArray *)validateObject:(NSObject *)object name:(NSString *)name validators:(NSArray *)validators; ++ (NSString *)errorMessageForDomain:(NSString *)domain; ++ (void)setErrorMessage:(NSString *)message forDomain:(NSString *)domain; ++ (void)setErrorMessages:(NSDictionary *)messages; + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.m b/RETableViewManagerExample/Vendor/REValidation/REValidation.m new file mode 100644 index 0000000..47c48d2 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.m @@ -0,0 +1,141 @@ +// +// REValidation.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidation.h" + +@interface REValidation () + +@property (strong, readwrite, nonatomic) NSMutableDictionary *registeredValidators; +@property (strong, readwrite, nonatomic) NSMutableDictionary *errorMessages; + +@end + +@implementation REValidation + ++ (instancetype)sharedObject +{ + static REValidation *_sharedClient = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + _sharedClient = [[REValidation alloc] init]; + }); + + return _sharedClient; +} + ++ (void)registerValidator:(Class)validatorClass +{ + [REValidation sharedObject].registeredValidators[[validatorClass name]] = NSStringFromClass(validatorClass); +} + ++ (void)registerDefaultValidators +{ + static BOOL registeredValidators; + if (!registeredValidators) { + [REValidation registerValidator:[REPresenceValidator class]]; + [REValidation registerValidator:[RELengthValidator class]]; + [REValidation registerValidator:[REEmailValidator class]]; + registeredValidators = YES; + } +} + ++ (void)registerDefaultErrorMessages +{ + static BOOL registeredMessages; + if (!registeredMessages) { + NSDictionary *messages = @{ + @"com.REValidation.presence": @"%@ can't be blank.", + @"com.REValidation.minimumLength": @"%@ is too short (minimum is %i characters).", + @"com.REValidation.maximumLength": @"%@ is too long (maximum is %i characters).", + @"com.REValidation.email": @"%@ is not a valid email.", + }; + [REValidation sharedObject].errorMessages = [NSMutableDictionary dictionaryWithDictionary:messages]; + registeredMessages = YES; + } +} + ++ (NSString *)errorMessageForDomain:(NSString *)domain +{ + return NSLocalizedString([REValidation sharedObject].errorMessages[domain], [REValidation sharedObject].errorMessages[domain]); +} + ++ (void)setErrorMessage:(NSString *)message forDomain:(NSString *)domain +{ + [REValidation sharedObject].errorMessages[domain] = message; +} + ++ (void)setErrorMessages:(NSDictionary *)messages +{ + [REValidation sharedObject].errorMessages = [NSMutableDictionary dictionaryWithDictionary:messages]; +} + ++ (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string +{ + NSString *validatorStringName = [string componentsSeparatedByString:@"("][0]; + for (NSString *validatorName in [REValidation sharedObject].registeredValidators) { + if ([validatorName isEqualToString:validatorStringName]) { + Class validator = NSClassFromString([REValidation sharedObject].registeredValidators[validatorName]); + return [[validator class] validateObject:object variableName:name parameters:[validator parseParameterString:string]]; + } + } + return nil; +} + ++ (NSError *)validateObject:(NSObject *)object name:(NSString *)name validator:(REValidator *)validator +{ + return [[validator class] validateObject:object variableName:name parameters:validator.parameters]; +} + ++ (NSArray *)validateObject:(NSObject *)object name:(NSString *)name validators:(NSArray *)validators +{ + NSMutableArray *errors = [NSMutableArray array]; + + for (id validator in validators) { + NSError *error; + if ([validator isKindOfClass:[NSString class]]) { + error = [self validateObject:object name:name validatorString:(NSString *)validator]; + } else { + error = [self validateObject:object name:name validator:validator]; + } + if (error) + [errors addObject:error]; + } + + return errors; +} + + +- (id)init +{ + self = [super init]; + if (!self) + return nil; + + self.registeredValidators = [[NSMutableDictionary alloc] init]; + + return self; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.h b/RETableViewManagerExample/Vendor/REValidation/REValidator.h new file mode 100644 index 0000000..b4c499b --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.h @@ -0,0 +1,39 @@ +// +// REValidator.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 REValidator : NSObject + +@property (strong, readonly, nonatomic) NSDictionary *parameters; + ++ (instancetype)validator; ++ (instancetype)validatorWithParameters:(NSDictionary *)parameters; + ++ (NSString *)name; ++ (NSDictionary *)parseParameterString:(NSString *)string; ++ (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters; + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.m b/RETableViewManagerExample/Vendor/REValidation/REValidator.m new file mode 100644 index 0000000..093a775 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.m @@ -0,0 +1,64 @@ +// +// REValidator.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidator.h" + +@interface REValidator () + +@property (strong, readwrite, nonatomic) NSDictionary *parameters; + +@end + +@implementation REValidator + ++ (instancetype)validatorWithParameters:(NSDictionary *)parameters +{ + REValidator *validator = [[self alloc] init]; + validator.parameters = parameters; + return validator; +} + ++ (instancetype)validator +{ + REValidator *validator = [[self alloc] init]; + return validator; +} + ++ (NSString *)name +{ + return @""; +} + ++ (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters +{ + return nil; +} + ++ (NSDictionary *)parseParameterString:(NSString *)string +{ + return nil; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.h b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.h new file mode 100644 index 0000000..705b354 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.h @@ -0,0 +1,30 @@ +// +// REEmailValidator.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidator.h" + +@interface REEmailValidator : REValidator + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m new file mode 100644 index 0000000..62e9c20 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m @@ -0,0 +1,48 @@ +// +// REEmailValidator.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REEmailValidator.h" +#import "REValidation.h" + +@implementation REEmailValidator + ++ (NSString *)name +{ + return @"email"; +} + ++ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters +{ + NSError *error = NULL; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" options:NSRegularExpressionCaseInsensitive error:&error]; + NSTextCheckingResult *match = [regex firstMatchInString:object options:0 range:NSMakeRange(0, object.length)]; + + if (!match) + return [NSError re_validationErrorForDomain:@"com.REValidation.email", name]; + + return nil; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.h b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.h new file mode 100644 index 0000000..0f0ba7e --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.h @@ -0,0 +1,30 @@ +// +// RELengthValidator.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidator.h" + +@interface RELengthValidator : REValidator + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m new file mode 100644 index 0000000..52542d2 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m @@ -0,0 +1,68 @@ +// +// RELengthValidator.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "RELengthValidator.h" +#import "NSError+REValidation.h" + +@implementation RELengthValidator + ++ (NSString *)name +{ + return @"length"; +} + ++ (NSDictionary *)parseParameterString:(NSString *)string +{ + NSError *error = NULL; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"(\\d+)" options:0 error:&error]; + NSArray *matches = [regex matchesInString:string options:0 range:NSMakeRange(0, string.length)]; + NSMutableArray *results = [NSMutableArray array]; + for (NSTextCheckingResult *matchResult in matches) { + NSString *match = [string substringWithRange:[matchResult range]]; + [results addObject:match]; + } + if (results.count == 2) { + return @{ @"min": results[0], @"max": results[1]}; + } + + return nil; +} + ++ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters +{ + NSUInteger minimumValue = [parameters[@"min"] integerValue]; + NSUInteger maximumValue = [parameters[@"max"] integerValue]; + + if (object.length < minimumValue && minimumValue > 0) + return [NSError re_validationErrorForDomain:@"com.REValidation.minimumLength", name, minimumValue]; + + if (object.length > maximumValue && maximumValue > 0) + return [NSError re_validationErrorForDomain:@"com.REValidation.maximumLength", name, maximumValue]; /*[NSError errorWithDomain:@"com.REValidation.maximumLength" code:1 userInfo:@{ NSLocalizedDescriptionKey: + [NSString stringWithFormat:NSLocalizedString(@"%@ is too long (maximum is %i characters).", @"%@ is too long (maximum is %i characters)."), name, maximumValue] + }];*/ + return nil; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.h b/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.h new file mode 100644 index 0000000..4ab42bb --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.h @@ -0,0 +1,30 @@ +// +// REPresenceValidator.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidator.h" + +@interface REPresenceValidator : REValidator + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.m new file mode 100644 index 0000000..7a907ff --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REPresenceValidator.m @@ -0,0 +1,44 @@ +// +// REPresenceValidator.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REPresenceValidator.h" +#import "NSError+REValidation.h" + +@implementation REPresenceValidator + ++ (NSString *)name +{ + return @"presence"; +} + ++ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters +{ + if (![object isKindOfClass:[NSString class]] || object.length == 0) + return [NSError re_validationErrorForDomain:@"com.REValidation.presence", name]; + + return nil; +} + +@end From 9c783608ba1db14ae388782f739cf6a068646ebe Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:07:45 -0500 Subject: [PATCH 13/44] Deselect previously selected item in RETableViewOptionsController, fix #14 --- RETableViewManager/RETableViewOptionsController.m | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/RETableViewManager/RETableViewOptionsController.m b/RETableViewManager/RETableViewOptionsController.m index 279376b..c6a7028 100644 --- a/RETableViewManager/RETableViewOptionsController.m +++ b/RETableViewManager/RETableViewOptionsController.m @@ -87,6 +87,14 @@ [_mainSection addItem:[RETableViewItem itemWithTitle:title accessoryType:accessoryType selectionHandler:^(RETableViewItem *selectedItem) { UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:selectedItem.indexPath]; if (!weakSelf.multipleChoice) { + for (NSIndexPath *indexPath in [weakSelf.tableView indexPathsForVisibleRows]) { + UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:indexPath]; + cell.accessoryType = UITableViewCellAccessoryNone; + } + for (RETableViewItem *item in weakSelf.mainSection.items) { + item.accessoryType = UITableViewCellAccessoryNone; + } + selectedItem.accessoryType = UITableViewCellAccessoryCheckmark; cell.accessoryType = UITableViewCellAccessoryCheckmark; RERadioItem * __weak item = (RERadioItem *)weakSelf.item; item.value = selectedItem.title; From 4ef179befea1975121746c99868a97670c5ff3fa Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:35:42 -0500 Subject: [PATCH 14/44] Add global items validation --- RETableViewManager/RETableViewManager.h | 6 ++++++ RETableViewManager/RETableViewManager.m | 17 +++++++++++++++++ RETableViewManager/RETableViewSection.h | 6 ++++++ RETableViewManager/RETableViewSection.m | 18 ++++++++++++++++++ .../Vendor/REValidation/REValidation.h | 15 ++++++++++++++- .../Vendor/REValidation/REValidator.h | 13 +++++++++++++ .../Vendor/REValidation/REValidator.m | 9 +++++++-- .../REValidation/Validators/REEmailValidator.m | 3 ++- .../Validators/RELengthValidator.m | 5 ++--- 9 files changed, 85 insertions(+), 7 deletions(-) diff --git a/RETableViewManager/RETableViewManager.h b/RETableViewManager/RETableViewManager.h index 98f7e59..f0f9842 100644 --- a/RETableViewManager/RETableViewManager.h +++ b/RETableViewManager/RETableViewManager.h @@ -335,6 +335,12 @@ BOOL REDeviceIsUIKit7(); */ - (void)sortSectionsUsingSelector:(SEL)comparator; +///----------------------------- +/// @name Checking for Validation Errors +///----------------------------- + +@property (strong, readonly, nonatomic) NSArray *errors; + @end diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 9b192f5..35f42b5 100644 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -911,4 +911,21 @@ BOOL REDeviceIsUIKit7() { [_sections sortUsingSelector:comparator]; } +#pragma mark - +#pragma mark Checking for errors + +- (NSArray *)errors +{ + NSMutableArray *errors; + for (RETableViewSection *section in self.sections) { + if (section.errors) { + if (!errors) { + errors = [[NSMutableArray alloc] init]; + } + [errors addObjectsFromArray:section.errors]; + } + } + return errors; +} + @end diff --git a/RETableViewManager/RETableViewSection.h b/RETableViewManager/RETableViewSection.h index 8f8d452..f5d97af 100644 --- a/RETableViewManager/RETableViewSection.h +++ b/RETableViewManager/RETableViewSection.h @@ -344,4 +344,10 @@ */ - (void)reloadSectionWithAnimation:(UITableViewRowAnimation)animation; +///----------------------------- +/// @name Checking for Validation Errors +///----------------------------- + +@property (strong, readonly, nonatomic) NSArray *errors; + @end \ No newline at end of file diff --git a/RETableViewManager/RETableViewSection.m b/RETableViewManager/RETableViewSection.m index 8fad822..eb322b6 100644 --- a/RETableViewManager/RETableViewSection.m +++ b/RETableViewManager/RETableViewSection.m @@ -281,4 +281,22 @@ [self.tableViewManager.tableView reloadSections:[NSIndexSet indexSetWithIndex:self.index] withRowAnimation:animation]; } +#pragma mark - +#pragma mark Checking for errors + +- (NSArray *)errors +{ + NSMutableArray *errors; + for (RETableViewItem *item in self.items) { + if ([item respondsToSelector:@selector(errors)] && item.errors) { + if (!errors) { + errors = [[NSMutableArray alloc] init]; + } + if (item.errors.count > 0) + [errors addObject:item.errors[0]]; + } + } + return errors; +} + @end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.h b/RETableViewManagerExample/Vendor/REValidation/REValidation.h index 9614ac3..8aefa97 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.h +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.h @@ -32,13 +32,26 @@ @interface REValidation : NSObject -+ (instancetype)sharedObject; +///----------------------------- +/// @name Registering Validators +///----------------------------- + + (void)registerDefaultValidators; + (void)registerDefaultErrorMessages; + (void)registerValidator:(Class)validatorClass; + +///----------------------------- +/// @name Validating Objects +///----------------------------- + + (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string; + (NSError *)validateObject:(NSObject *)object name:(NSString *)name validator:(REValidator *)validator; + (NSArray *)validateObject:(NSObject *)object name:(NSString *)name validators:(NSArray *)validators; + +///----------------------------- +/// @name Handling Error Messages +///----------------------------- + + (NSString *)errorMessageForDomain:(NSString *)domain; + (void)setErrorMessage:(NSString *)message forDomain:(NSString *)domain; + (void)setErrorMessages:(NSDictionary *)messages; diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.h b/RETableViewManagerExample/Vendor/REValidation/REValidator.h index b4c499b..857a910 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.h +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.h @@ -29,11 +29,24 @@ @property (strong, readonly, nonatomic) NSDictionary *parameters; +///----------------------------- +/// @name Getting Validator Instance +///----------------------------- + + (instancetype)validator; + (instancetype)validatorWithParameters:(NSDictionary *)parameters; +///----------------------------- +/// @name Configuring Representation +///----------------------------- + + (NSString *)name; + (NSDictionary *)parseParameterString:(NSString *)string; + +///----------------------------- +/// @name Validating Objects +///----------------------------- + + (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters; @end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.m b/RETableViewManagerExample/Vendor/REValidation/REValidator.m index 093a775..84b8034 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.m @@ -42,8 +42,7 @@ + (instancetype)validator { - REValidator *validator = [[self alloc] init]; - return validator; + return [[self alloc] init]; } + (NSString *)name @@ -62,3 +61,9 @@ } @end +ring *)string +{ + return nil; +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m index 62e9c20..0c1ecda 100644 --- a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m @@ -35,9 +35,10 @@ + (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters { + NSString *string = object ? object : @""; NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" options:NSRegularExpressionCaseInsensitive error:&error]; - NSTextCheckingResult *match = [regex firstMatchInString:object options:0 range:NSMakeRange(0, object.length)]; + NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)]; if (!match) return [NSError re_validationErrorForDomain:@"com.REValidation.email", name]; diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m index 52542d2..bf1b7fd 100644 --- a/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/RELengthValidator.m @@ -59,9 +59,8 @@ return [NSError re_validationErrorForDomain:@"com.REValidation.minimumLength", name, minimumValue]; if (object.length > maximumValue && maximumValue > 0) - return [NSError re_validationErrorForDomain:@"com.REValidation.maximumLength", name, maximumValue]; /*[NSError errorWithDomain:@"com.REValidation.maximumLength" code:1 userInfo:@{ NSLocalizedDescriptionKey: - [NSString stringWithFormat:NSLocalizedString(@"%@ is too long (maximum is %i characters).", @"%@ is too long (maximum is %i characters)."), name, maximumValue] - }];*/ + return [NSError re_validationErrorForDomain:@"com.REValidation.maximumLength", name, maximumValue]; + return nil; } From 86c5fe879bb799e3db3dad824736712e89bfc824 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:47:58 -0500 Subject: [PATCH 15/44] Add validations example --- .../project.pbxproj | 6 ++ .../Classes/Controllers/RootViewController.m | 6 ++ .../Controllers/ValidationsViewController.h | 16 +++++ .../Controllers/ValidationsViewController.m | 68 +++++++++++++++++++ .../Vendor/REValidation/REValidator.m | 6 -- 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.h create mode 100644 RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m diff --git a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj index 83e5782..0160865 100644 --- a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj +++ b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj @@ -45,6 +45,7 @@ 30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5917C56EEF0010D439 /* REEmailValidator.m */; }; 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */; }; 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */; }; + 30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D7917C667A90010D439 /* ValidationsViewController.m */; }; 30D1C7D617AC08F4001F731C /* First_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */; }; 30D1C7D717AC08F4001F731C /* Last_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */; }; 30D1C7D817AC08F4001F731C /* Middle_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */; }; @@ -153,6 +154,8 @@ 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RELengthValidator.m; sourceTree = ""; }; 30B00D5C17C56EEF0010D439 /* REPresenceValidator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = REPresenceValidator.h; sourceTree = ""; }; 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REPresenceValidator.m; sourceTree = ""; }; + 30B00D7817C667A90010D439 /* ValidationsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationsViewController.h; sourceTree = ""; }; + 30B00D7917C667A90010D439 /* ValidationsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ValidationsViewController.m; sourceTree = ""; }; 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "First_Alt@2x.png"; path = "Resources/First_Alt@2x.png"; sourceTree = ""; }; 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Last_Alt@2x.png"; path = "Resources/Last_Alt@2x.png"; sourceTree = ""; }; 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Middle_Alt@2x.png"; path = "Resources/Middle_Alt@2x.png"; sourceTree = ""; }; @@ -268,6 +271,8 @@ 303D967117B7CDE300A418F3 /* XIBTestViewController.m */, 30E5F50A17BBD163005CF1FE /* IndexedListViewController.h */, 30E5F50B17BBD163005CF1FE /* IndexedListViewController.m */, + 30B00D7817C667A90010D439 /* ValidationsViewController.h */, + 30B00D7917C667A90010D439 /* ValidationsViewController.m */, ); path = Controllers; sourceTree = ""; @@ -645,6 +650,7 @@ 30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */, 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */, 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */, + 30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/RootViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/RootViewController.m index 01b03a2..290ed74 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/RootViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/RootViewController.m @@ -14,6 +14,7 @@ #import "StylingViewController.h" #import "XIBTestViewController.h" #import "IndexedListViewController.h" +#import "ValidationsViewController.h" @interface RootViewController () @@ -71,6 +72,11 @@ [item deselectRowAnimated:YES]; [weakSelf.navigationController pushViewController:[[IndexedListViewController alloc] initWithStyle:UITableViewStylePlain] animated:YES]; }]]; + + [section addItem:[RETableViewItem itemWithTitle:@"Validations" accessoryType:UITableViewCellAccessoryDisclosureIndicator selectionHandler:^(RETableViewItem *item) { + [item deselectRowAnimated:YES]; + [weakSelf.navigationController pushViewController:[[ValidationsViewController alloc] initWithStyle:UITableViewStyleGrouped] animated:YES]; + }]]; } @end diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.h b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.h new file mode 100644 index 0000000..0762806 --- /dev/null +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.h @@ -0,0 +1,16 @@ +// +// ValidationsViewController.h +// RETableViewManagerExample +// +// Created by Roman Efimov on 8/22/13. +// Copyright (c) 2013 Roman Efimov. All rights reserved. +// + +#import +#import "RETableViewManager.h" + +@interface ValidationsViewController : UITableViewController + +@property (strong, readonly, nonatomic) RETableViewManager *manager; + +@end diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m new file mode 100644 index 0000000..11c06ed --- /dev/null +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m @@ -0,0 +1,68 @@ +// +// ValidationsViewController.m +// RETableViewManagerExample +// +// Created by Roman Efimov on 8/22/13. +// Copyright (c) 2013 Roman Efimov. All rights reserved. +// + +#import "ValidationsViewController.h" + +@interface ValidationsViewController () + +@property (strong, readwrite, nonatomic) RETextItem *textItem; +@property (strong, readwrite, nonatomic) RETextItem *emailItem; + +@end + +@implementation ValidationsViewController + +- (void)viewDidLoad +{ + [super viewDidLoad]; + self.title = @"Controls"; + self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Validate" style:UIBarButtonItemStyleBordered target:self action:@selector(validateButtonPressed:)]; + + // Create manager + // + _manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; + + // Add a section + // + RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Basic controls"]; + [_manager addSection:section]; + + // Add items + // + self.textItem = [RETextItem itemWithTitle:@"Text" value:@"" placeholder:@"Text item"]; + self.textItem.validators = @[@"presence", @"length(3, 10)"]; + + self.emailItem = [RETextItem itemWithTitle:@"Email" value:@"" placeholder:@"Email item"]; + self.emailItem.name = @"Your email"; + self.emailItem.keyboardType = UIKeyboardTypeEmailAddress; + self.emailItem.autocapitalizationType = UITextAutocapitalizationTypeNone; + self.emailItem.validators = @[@"presence", @"email"]; + + [section addItem:self.textItem]; + [section addItem:self.emailItem]; +} + +#pragma mark - +#pragma mark Button actions + +- (void)validateButtonPressed:(UIButton *)sender +{ + if (self.manager.errors) { + NSMutableArray *errors = [NSMutableArray array]; + for (NSError *error in self.manager.errors) { + [errors addObject:error.localizedDescription]; + } + NSString *errorString = [errors componentsJoinedByString:@"\n"]; + UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Errors" message:errorString delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alert show]; + } else { + NSLog(@"All good, no errors!"); + } +} + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.m b/RETableViewManagerExample/Vendor/REValidation/REValidator.m index 84b8034..55d01b5 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.m @@ -61,9 +61,3 @@ } @end -ring *)string -{ - return nil; -} - -@end From 09a4315d1c5c099220251336739be2a6bfed9901 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:49:23 -0500 Subject: [PATCH 16/44] Update example project --- .../Classes/Controllers/ValidationsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m index 11c06ed..3b85b32 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m @@ -52,7 +52,7 @@ - (void)validateButtonPressed:(UIButton *)sender { - if (self.manager.errors) { + if (self.manager.errors.count > 0) { NSMutableArray *errors = [NSMutableArray array]; for (NSError *error in self.manager.errors) { [errors addObject:error.localizedDescription]; From acb58a2ff3ef3f2bb12ec6d11297fdb4b2b16fad Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:52:25 -0500 Subject: [PATCH 17/44] Update readme --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6867d61..71e0838 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.1.3' +pod 'RETableViewManager', '~> 1.2' ``` Install into your Xcode project: @@ -364,6 +364,21 @@ RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test" [section addItem:[REDateTimeItem itemWithTitle:@"Date / Time" value:[NSDate date] placeholder:nil format:@"MM/dd/yyyy hh:mm a" datePickerMode:UIDatePickerModeDateAndTime]]; ``` +### Validations + +Validations are performed using [REValidation](https://github.com/romaonthego/REValidation) library. + +Example: + +```objective-c + self.textItem = [RETextItem itemWithTitle:@"Text" value:@"" placeholder:@"Text item"]; +self.textItem.validators = @[@"presence", @"length(3, 10)"]; + +self.emailItem = [RETextItem itemWithTitle:@"Email" value:@"" placeholder:@"Email item"]; +self.emailItem.name = @"Your email"; +self.emailItem.validators = @[@"presence", @"email"]; +``` + ### Custom Cells `RETableViewManager` allows to map custom objects to custom cells. In order to map your custom object (an item) to a cell, From 005cdf7a167371db72e3297828e172792c0ceb7f Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:52:59 -0500 Subject: [PATCH 18/44] Fix typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 71e0838..0dcedf5 100644 --- a/README.md +++ b/README.md @@ -371,7 +371,7 @@ Validations are performed using [REValidation](https://github.com/romaonthego/RE Example: ```objective-c - self.textItem = [RETextItem itemWithTitle:@"Text" value:@"" placeholder:@"Text item"]; +self.textItem = [RETextItem itemWithTitle:@"Text" value:@"" placeholder:@"Text item"]; self.textItem.validators = @[@"presence", @"length(3, 10)"]; self.emailItem = [RETextItem itemWithTitle:@"Email" value:@"" placeholder:@"Email item"]; From fe9bd3e3b1ebef259da8a39010b307f6b4c68c64 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 22 Aug 2013 10:56:17 -0500 Subject: [PATCH 19/44] Update readme --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 0dcedf5..ae3411d 100644 --- a/README.md +++ b/README.md @@ -379,6 +379,10 @@ self.emailItem.name = @"Your email"; self.emailItem.validators = @[@"presence", @"email"]; ``` +Each item, each section and the manager have property `errors`. This property is always up to date with errors on each level. +For example, an `RETableViewItem` would only have its own validation errors, `RETableViewSection` would have all errors that occured in that section (one per item). +`RETableViewManager`'s property `errors` would reflect all errors. + ### Custom Cells `RETableViewManager` allows to map custom objects to custom cells. In order to map your custom object (an item) to a cell, From bca9e837bccd61fd082d74769177c99fef555c61 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sun, 25 Aug 2013 11:18:13 -0500 Subject: [PATCH 20/44] Fix compatibility issue with storyboards when cellDidLoad is never being called, closes #19 --- RETableViewManager/RETableViewCell.h | 2 ++ RETableViewManager/RETableViewCell.m | 7 +++++++ RETableViewManager/RETableViewManager.m | 13 +++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) mode change 100644 => 100755 RETableViewManager/RETableViewCell.h mode change 100644 => 100755 RETableViewManager/RETableViewCell.m mode change 100644 => 100755 RETableViewManager/RETableViewManager.m diff --git a/RETableViewManager/RETableViewCell.h b/RETableViewManager/RETableViewCell.h old mode 100644 new mode 100755 index 736c82a..f2999c8 --- a/RETableViewManager/RETableViewCell.h +++ b/RETableViewManager/RETableViewCell.h @@ -96,4 +96,6 @@ typedef NS_ENUM(NSInteger, RETableViewCellType) { - (void)cellWillAppear; - (void)cellDidDisappear; +@property (assign, readonly, nonatomic) BOOL loaded; + @end diff --git a/RETableViewManager/RETableViewCell.m b/RETableViewManager/RETableViewCell.m old mode 100644 new mode 100755 index 690c1f5..e7147c6 --- a/RETableViewManager/RETableViewCell.m +++ b/RETableViewManager/RETableViewCell.m @@ -26,6 +26,12 @@ #import "RETableViewCell.h" #import "RETableViewManager.h" +@interface RETableViewCell () + +@property (assign, readwrite, nonatomic) BOOL loaded; + +@end + @implementation RETableViewCell + (BOOL)canFocusWithItem:(RETableViewItem *)item @@ -71,6 +77,7 @@ - (void)cellDidLoad { + self.loaded = YES; self.actionBar = [[REActionBar alloc] initWithDelegate:self]; self.selectionStyle = self.tableViewManager.style.defaultCellSelectionStyle; diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m old mode 100644 new mode 100755 index 35f42b5..a23b669 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -189,8 +189,8 @@ BOOL REDeviceIsUIKit7() { } RETableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; - if (cell == nil) { - cell = [[cellClass alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier]; + + void (^loadCell)(RETableViewCell *cell) = ^(RETableViewCell *cell) { cell.tableViewManager = self; // RETableViewManagerDelegate @@ -204,6 +204,15 @@ BOOL REDeviceIsUIKit7() { // if ([_delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [_delegate respondsToSelector:@selector(tableView:didLoadCell:forRowAtIndexPath:)]) [_delegate tableView:tableView didLoadCell:cell forRowAtIndexPath:indexPath]; + }; + + if (cell == nil) { + cell = [[cellClass alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier]; + loadCell(cell); + } + + if ([cell isKindOfClass:[RETableViewCell class]] && [cell respondsToSelector:@selector(loaded)] && !cell.loaded) { + loadCell(cell); } cell.rowIndex = indexPath.row; From 2f1a89dbd089ea8e2e7d538173a115b9f2573894 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sun, 25 Aug 2013 11:20:51 -0500 Subject: [PATCH 21/44] Version bump (1.2.1) --- README.md | 2 +- RETableViewManager.podspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ae3411d..dc6d696 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.2' +pod 'RETableViewManager', '~> 1.2.1' ``` Install into your Xcode project: diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index fc416e9..7b66c8d 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.1.3' + s.version = '1.2.1' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.1.3' } + :tag => '1.2.1' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' From 42af6472e895c6e6f40cc8a4fc1499ff88a1317e Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sun, 25 Aug 2013 15:50:44 -0500 Subject: [PATCH 22/44] Update README.md --- README.md | 54 +++++++++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index dc6d696..d554bb7 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ Get your `UITableView` up and running in several lines of code: // Create the manager and assign a UITableView // - _manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; + self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // @@ -43,7 +43,7 @@ Get your `UITableView` up and running in several lines of code: // Custom items / cells // - _manager[@"CustomItem"] = @"CustomCell"; + self.manager[@"CustomItem"] = @"CustomCell"; [section addItem:[CustomItem item]]; } @@ -220,35 +220,35 @@ Section without a title: ``` objective-c RETableViewSection *section = [RETableViewSection section]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; ``` Section with a title: ``` objective-c RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Header"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; ``` Section with a title and a footer: ``` objective-c RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Header" footerTitle:@"Footer"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; ``` Section with a custom header view: ``` objective-c RETableViewSection *section = [RETableViewSection sectionWithHeaderView:myCustomSectionHeaderView]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; ``` Section with a custom header and footer view: ``` objective-c RETableViewSection *section = [RETableViewSection sectionWithHeaderView:myCustomSectionHeaderView footerView:myCustomSectionFooterView]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; ``` ### Text (UITextField) and Number (REFormattedNumberField) Item Example @@ -256,35 +256,35 @@ RETableViewSection *section = [RETableViewSection sectionWithHeaderView:myCustom ``` objective-c // Create the manager // -_tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView]; +self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; // Add items to the section // -_textItem = [RETextItem itemWithTitle:@"Enter text" value:@""]; -[section addItem:_textItem]; +self.textItem = [RETextItem itemWithTitle:@"Enter text" value:@""]; +[section addItem:self.textItem]; -_numberItem = [RENumberItem itemWithTitle:@"Enter text" value:@"" placeholder:@"(123) 456-7890" format:@"(XXX) XXX-XXXX"]; -[section addItem:_numberItem]; +self.numberItem = [RENumberItem itemWithTitle:@"Enter text" value:@"" placeholder:@"(123) 456-7890" format:@"(XXX) XXX-XXXX"]; +[section addItem:self.numberItem]; ``` -You can read `_textItem.value` and `_numberItem.value` later whenever you need them. +You can read `self.textItem.value` and `self.numberItem.value` later whenever you need them. ### Bool Item (UISwitch) Example ``` objective-c // Create the manager // -_tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView]; +self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; // Add a bool value cell (using UISwitch) // @@ -298,12 +298,12 @@ RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test" ``` objective-c // Create the manager // -_tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView]; +self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; // Add radio cell (options) // @@ -333,12 +333,12 @@ RERadioItem *optionItem = [RERadioItem itemWithTitle:@"Radio" value:@"Option 4" ``` objective-c // Create the manager // -_tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView]; +self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; // Add a float item // @@ -352,12 +352,12 @@ RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test" ``` objective-c // Create the manager // -_tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView]; +self.manager = [[RETableViewManager alloc] initWithTableView:self.tableView]; // Add a section // RETableViewSection *section = [RETableViewSection sectionWithHeaderTitle:@"Test"]; -[_tableViewManager addSection:section]; +[self.manager addSection:section]; // Add a date item // @@ -389,7 +389,7 @@ For example, an `RETableViewItem` would only have its own validation errors, `RE simply write: ```objective-c -_manager[@"CustomItem"] = @"CustomCell"; +self.manager[@"CustomItem"] = @"CustomCell"; ``` If you take a look at [RETableViewManager Source Code](https://github.com/romaonthego/RETableViewManager/blob/master/RETableViewManager/RETableViewManager.m) you may @@ -464,13 +464,13 @@ Quick example: ```objective-c - (void)cellDidLoad { - _testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; - [self.contentView addSubview:_testLabel]; + self.testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; + [self.contentView addSubview:self.testLabel]; } - (void)cellWillAppear { - _testLabel.text = self.item.someVariable; + self.testLabel.text = self.item.someVariable; } ``` @@ -480,7 +480,7 @@ Interface builder cells are supported out of the box, no special set up needed. Cells and items are being automatically registered like any other custom cell in `RETableViewManager`: ```objective-c -_manager[@"XIBTestItem"] = @"XIBTestCell"; +self.manager[@"XIBTestItem"] = @"XIBTestCell"; ``` Here `XIBTestItem` would be your cell identifier and you should have the `XIBTestCell.xib` file in your bundle. That's it. From 844ee02bb9a6fe5af332699683a780e1548daffd Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sun, 25 Aug 2013 17:51:13 -0500 Subject: [PATCH 23/44] Update podspec dependency --- RETableViewManager.podspec | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index 7b66c8d..a0a629c 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.2.1' + s.version = '1.2.2' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.2.1' } + :tag => '1.2.2' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' @@ -17,4 +17,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '6.0' s.dependency 'REFormattedNumberField', '~> 1.0.4' + s.dependency 'REValidation', '~> 0.1.1' end From 49fc68fdef3735bd89d3b88ccdea331381691a5c Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sun, 25 Aug 2013 17:51:33 -0500 Subject: [PATCH 24/44] Version bump (1.2.2) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d554bb7..0a5ba1f 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.2.1' +pod 'RETableViewManager', '~> 1.2.2' ``` Install into your Xcode project: From acfc2b9dbd028d5d5dd2335ad03c6f931f702255 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Mon, 26 Aug 2013 12:17:06 -0500 Subject: [PATCH 25/44] Trigger RERadioItem KVO, fix #20 --- RETableViewManager/RETableViewOptionsController.m | 2 ++ 1 file changed, 2 insertions(+) diff --git a/RETableViewManager/RETableViewOptionsController.m b/RETableViewManager/RETableViewOptionsController.m index c6a7028..f051910 100644 --- a/RETableViewManager/RETableViewOptionsController.m +++ b/RETableViewManager/RETableViewOptionsController.m @@ -97,7 +97,9 @@ selectedItem.accessoryType = UITableViewCellAccessoryCheckmark; cell.accessoryType = UITableViewCellAccessoryCheckmark; RERadioItem * __weak item = (RERadioItem *)weakSelf.item; + [item willChangeValueForKey:@"value"]; item.value = selectedItem.title; + [item didChangeValueForKey:@"value"]; if (weakSelf.completionHandler) weakSelf.completionHandler(); } else { // Multiple choice item From 23f3fcba0a205748191da7c3c80f827e631c6ba5 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Mon, 26 Aug 2013 12:31:16 -0500 Subject: [PATCH 26/44] Remove custom getter / setters, so KVO works properly, issue #20 --- RETableViewManager/Items/RERadioItem.h | 2 +- RETableViewManager/Items/RERadioItem.m | 6 ++++++ RETableViewManager/RETableViewOptionsController.m | 2 -- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/RETableViewManager/Items/RERadioItem.h b/RETableViewManager/Items/RERadioItem.h index 73b7f06..dcd10e9 100644 --- a/RETableViewManager/Items/RERadioItem.h +++ b/RETableViewManager/Items/RERadioItem.h @@ -27,7 +27,7 @@ @interface RERadioItem : RETableViewItem -@property (strong, readwrite, nonatomic, getter = detailLabelText, setter = setDetailLabelText:) NSString *value; +@property (strong, readwrite, nonatomic) NSString *value; + (instancetype)itemWithTitle:(NSString *)title value:(NSString *)value selectionHandler:(void(^)(RERadioItem *item))selectionHandler; - (id)initWithTitle:(NSString *)title value:(NSString *)value selectionHandler:(void(^)(RERadioItem *item))selectionHandler; diff --git a/RETableViewManager/Items/RERadioItem.m b/RETableViewManager/Items/RERadioItem.m index 32b6919..0a2df8c 100644 --- a/RETableViewManager/Items/RERadioItem.m +++ b/RETableViewManager/Items/RERadioItem.m @@ -47,4 +47,10 @@ return self; } +- (void)setValue:(NSString *)value +{ + _value = value; + self.detailLabelText = value; +} + @end diff --git a/RETableViewManager/RETableViewOptionsController.m b/RETableViewManager/RETableViewOptionsController.m index f051910..c6a7028 100644 --- a/RETableViewManager/RETableViewOptionsController.m +++ b/RETableViewManager/RETableViewOptionsController.m @@ -97,9 +97,7 @@ selectedItem.accessoryType = UITableViewCellAccessoryCheckmark; cell.accessoryType = UITableViewCellAccessoryCheckmark; RERadioItem * __weak item = (RERadioItem *)weakSelf.item; - [item willChangeValueForKey:@"value"]; item.value = selectedItem.title; - [item didChangeValueForKey:@"value"]; if (weakSelf.completionHandler) weakSelf.completionHandler(); } else { // Multiple choice item From 3cde2fe12c08795bdee7a4324fb77db697231e6b Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Mon, 26 Aug 2013 12:31:43 -0500 Subject: [PATCH 27/44] Strong -> Copy --- RETableViewManager/Items/RERadioItem.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RETableViewManager/Items/RERadioItem.h b/RETableViewManager/Items/RERadioItem.h index dcd10e9..61ac590 100644 --- a/RETableViewManager/Items/RERadioItem.h +++ b/RETableViewManager/Items/RERadioItem.h @@ -27,7 +27,7 @@ @interface RERadioItem : RETableViewItem -@property (strong, readwrite, nonatomic) NSString *value; +@property (copy, readwrite, nonatomic) NSString *value; + (instancetype)itemWithTitle:(NSString *)title value:(NSString *)value selectionHandler:(void(^)(RERadioItem *item))selectionHandler; - (id)initWithTitle:(NSString *)title value:(NSString *)value selectionHandler:(void(^)(RERadioItem *item))selectionHandler; From 1891ec8f584d84d6f89893f0772268a78190922c Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Mon, 26 Aug 2013 12:32:59 -0500 Subject: [PATCH 28/44] Version bump (1.2.3) --- README.md | 2 +- RETableViewManager.podspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0a5ba1f..1985a89 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.2.2' +pod 'RETableViewManager', '~> 1.2.3' ``` Install into your Xcode project: diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index a0a629c..3237b48 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.2.2' + s.version = '1.2.3' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.2.2' } + :tag => '1.2.3' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' From 95e904059086e24b8ef2b08675e79db233308f3a Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sat, 31 Aug 2013 07:23:41 -0600 Subject: [PATCH 29/44] Update ListImageCell.m --- .../RETableViewManagerExample/Classes/Views/ListImageCell.m | 1 + 1 file changed, 1 insertion(+) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m index 81395c8..44eacb5 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m @@ -17,6 +17,7 @@ - (void)cellDidLoad { + self.loaded = YES; _pictureView = [[UIImageView alloc] initWithFrame:CGRectMake(7, 0, 306, 306)]; _pictureView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self addSubview:_pictureView]; From 9336f20b1b547034abe04f7f8c694f5dd610ddc7 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Sat, 31 Aug 2013 07:26:03 -0600 Subject: [PATCH 30/44] Update ListImageCell.m --- .../RETableViewManagerExample/Classes/Views/ListImageCell.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m index 44eacb5..5436f4c 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Views/ListImageCell.m @@ -17,7 +17,7 @@ - (void)cellDidLoad { - self.loaded = YES; + [super cellDidLoad]; _pictureView = [[UIImageView alloc] initWithFrame:CGRectMake(7, 0, 306, 306)]; _pictureView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleRightMargin; [self addSubview:_pictureView]; From af5a82b13ea49c1f1d642ec7df2b171f4531f26a Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 10:48:19 -0500 Subject: [PATCH 31/44] Check if an item is kind of RETableViewItem class in editingStyleForRowAtIndexPath, fix #25 --- RETableViewManager/RETableViewManager.m | 3 +++ 1 file changed, 3 insertions(+) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index a23b669..a5c62bb 100755 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -539,6 +539,9 @@ BOOL REDeviceIsUIKit7() { RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; + if (![item isKindOfClass:[RETableViewItem class]]) + return UITableViewCellEditingStyleNone; + // Forward to UITableView delegate // if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)]) From 7800c536405891f394bafc4fb4076d1bba419b8a Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 10:49:26 -0500 Subject: [PATCH 32/44] Version bump (1.2.4) --- README.md | 2 +- RETableViewManager.podspec | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1985a89..a190c0b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.2.3' +pod 'RETableViewManager', '~> 1.2.4' ``` Install into your Xcode project: diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index 3237b48..5166486 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.2.3' + s.version = '1.2.4' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.2.3' } + :tag => '1.2.4' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' From 4fe1e1e5cdaa58e6eb946f26b0b366caf48f2eab Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 11:01:00 -0500 Subject: [PATCH 33/44] Use properties instead of iVars in RETableViewManager.m --- RETableViewManager/RETableViewManager.m | 280 ++++++++++++------------ 1 file changed, 140 insertions(+), 140 deletions(-) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index a5c62bb..b286a42 100755 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -88,10 +88,10 @@ BOOL REDeviceIsUIKit7() { self.tableView = tableView; - _sections = [[NSMutableArray alloc] init]; - _registeredClasses = [[NSMutableDictionary alloc] init]; - _registeredXIBs = [[NSMutableDictionary alloc] init]; - _style = [[RETableViewCellStyle alloc] init]; + self.sections = [[NSMutableArray alloc] init]; + self.registeredClasses = [[NSMutableDictionary alloc] init]; + self.registeredXIBs = [[NSMutableDictionary alloc] init]; + self.style = [[RETableViewCellStyle alloc] init]; [self registerDefaultClasses]; @@ -131,7 +131,7 @@ BOOL REDeviceIsUIKit7() { - (id)objectAtKeyedSubscript:(id )key { - return [_registeredClasses objectForKey:key]; + return [self.registeredClasses objectForKey:key]; } - (void)setObject:(id)obj forKeyedSubscript:(id )key @@ -141,13 +141,13 @@ BOOL REDeviceIsUIKit7() { - (Class)classForCellAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; NSObject *item = [section.items objectAtIndex:indexPath.row]; Class cellClass; - for (NSString *className in _registeredClasses) { + for (NSString *className in self.registeredClasses) { NSString *itemClass = NSStringFromClass([item class]); if ([itemClass isEqualToString:className]) { - cellClass = NSClassFromString([_registeredClasses objectForKey:className]); + cellClass = NSClassFromString([self.registeredClasses objectForKey:className]); break; } } @@ -159,17 +159,17 @@ BOOL REDeviceIsUIKit7() { - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return _sections.count; + return self.sections.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex { - return ((RETableViewSection *)[_sections objectAtIndex:sectionIndex]).items.count; + return ((RETableViewSection *)[self.sections objectAtIndex:sectionIndex]).items.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; UITableViewCellStyle cellStyle = UITableViewCellStyleDefault; @@ -195,15 +195,15 @@ BOOL REDeviceIsUIKit7() { // RETableViewManagerDelegate // - if ([_delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [_delegate respondsToSelector:@selector(tableView:willLoadCell:forRowAtIndexPath:)]) - [_delegate tableView:tableView willLoadCell:cell forRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willLoadCell:forRowAtIndexPath:)]) + [self.delegate tableView:tableView willLoadCell:cell forRowAtIndexPath:indexPath]; [cell cellDidLoad]; // RETableViewManagerDelegate // - if ([_delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [_delegate respondsToSelector:@selector(tableView:didLoadCell:forRowAtIndexPath:)]) - [_delegate tableView:tableView didLoadCell:cell forRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(RETableViewManagerDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didLoadCell:forRowAtIndexPath:)]) + [self.delegate tableView:tableView didLoadCell:cell forRowAtIndexPath:indexPath]; }; if (cell == nil) { @@ -250,23 +250,23 @@ BOOL REDeviceIsUIKit7() { - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; return section.headerTitle; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; return section.footerTitle; } - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { - RETableViewSection *sourceSection = [_sections objectAtIndex:sourceIndexPath.section]; + RETableViewSection *sourceSection = [self.sections objectAtIndex:sourceIndexPath.section]; RETableViewItem *item = [sourceSection.items objectAtIndex:sourceIndexPath.row]; [sourceSection removeItemAtIndex:sourceIndexPath.row]; - RETableViewSection *destinationSection = [_sections objectAtIndex:destinationIndexPath.section]; + RETableViewSection *destinationSection = [self.sections objectAtIndex:destinationIndexPath.section]; [destinationSection insertItem:item atIndex:destinationIndexPath.row]; if (item.moveCompletionHandler) @@ -275,14 +275,14 @@ BOOL REDeviceIsUIKit7() { - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; return item.moveHandler != nil; } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if ([item isKindOfClass:[RETableViewItem class]]) { return item.editingStyle != UITableViewCellEditingStyleNone || item.moveHandler; @@ -294,7 +294,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (item.deletionHandlerWithCompletion) { item.deletionHandlerWithCompletion(item, ^{ @@ -310,7 +310,7 @@ BOOL REDeviceIsUIKit7() { } if (editingStyle == UITableViewCellEditingStyleInsert) { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (item.insertionHandler) item.insertionHandler(item); @@ -326,24 +326,24 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)]) - [_delegate tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)]) + [self.delegate tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willDisplayHeaderView:forSection:)]) - [_delegate tableView:tableView willDisplayHeaderView:view forSection:section]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willDisplayHeaderView:forSection:)]) + [self.delegate tableView:tableView willDisplayHeaderView:view forSection:section]; } - (void)tableView:(UITableView *)tableView willDisplayFooterView:(UIView *)view forSection:(NSInteger)section { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willDisplayFooterView:forSection:)]) - [_delegate tableView:tableView willDisplayFooterView:view forSection:section]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willDisplayFooterView:forSection:)]) + [self.delegate tableView:tableView willDisplayFooterView:view forSection:section]; } - (void)tableView:(UITableView *)tableView didEndDisplayingCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath*)indexPath @@ -353,65 +353,65 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didEndDisplayingCell:forRowAtIndexPath:)]) - [_delegate tableView:tableView didEndDisplayingCell:cell forRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didEndDisplayingCell:forRowAtIndexPath:)]) + [self.delegate tableView:tableView didEndDisplayingCell:cell forRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView *)tableView didEndDisplayingHeaderView:(UIView *)view forSection:(NSInteger)section { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didEndDisplayingHeaderView:forSection:)]) - [_delegate tableView:tableView didEndDisplayingHeaderView:view forSection:section]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didEndDisplayingHeaderView:forSection:)]) + [self.delegate tableView:tableView didEndDisplayingHeaderView:view forSection:section]; } - (void)tableView:(UITableView *)tableView didEndDisplayingFooterView:(UIView *)view forSection:(NSInteger)section { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didEndDisplayingFooterView:forSection:)]) - [_delegate tableView:tableView didEndDisplayingFooterView:view forSection:section]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didEndDisplayingFooterView:forSection:)]) + [self.delegate tableView:tableView didEndDisplayingFooterView:view forSection:section]; } // Variable height support - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)]) - return [_delegate tableView:tableView heightForRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:heightForRowAtIndexPath:)]) + return [self.delegate tableView:tableView heightForRowAtIndexPath:indexPath]; return [[self classForCellAtIndexPath:indexPath] heightWithItem:item tableViewManager:self]; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; if (section.headerView) return section.headerView.frame.size.height; // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)]) - return [_delegate tableView:tableView heightForHeaderInSection:sectionIndex]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:heightForHeaderInSection:)]) + return [self.delegate tableView:tableView heightForHeaderInSection:sectionIndex]; return UITableViewAutomaticDimension; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; if (section.footerView) return section.footerView.frame.size.height; // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:heightForFooterInSection:)]) - return [_delegate tableView:tableView heightForFooterInSection:sectionIndex]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:heightForFooterInSection:)]) + return [self.delegate tableView:tableView heightForFooterInSection:sectionIndex]; return UITableViewAutomaticDimension; } @@ -420,24 +420,24 @@ BOOL REDeviceIsUIKit7() { - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)]) - return [_delegate tableView:tableView viewForHeaderInSection:sectionIndex]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:viewForHeaderInSection:)]) + return [self.delegate tableView:tableView viewForHeaderInSection:sectionIndex]; return section.headerView; } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [_sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:viewForFooterInSection:)]) - return [_delegate tableView:tableView viewForFooterInSection:sectionIndex]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:viewForFooterInSection:)]) + return [self.delegate tableView:tableView viewForFooterInSection:sectionIndex]; return section.footerView; } @@ -446,7 +446,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; if ([item respondsToSelector:@selector(setAccessoryButtonTapHandler:)]) { RETableViewItem *actionItem = (RETableViewItem *)item; @@ -456,8 +456,8 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:accessoryButtonTappedForRowWithIndexPath:)]) - [_delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:accessoryButtonTappedForRowWithIndexPath:)]) + [self.delegate tableView:tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; } // Selection @@ -466,8 +466,8 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:shouldHighlightRowAtIndexPath:)]) - return [_delegate tableView:tableView shouldHighlightRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:shouldHighlightRowAtIndexPath:)]) + return [self.delegate tableView:tableView shouldHighlightRowAtIndexPath:indexPath]; return YES; } @@ -476,24 +476,24 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didHighlightRowAtIndexPath:)]) - [_delegate tableView:tableView didHighlightRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didHighlightRowAtIndexPath:)]) + [self.delegate tableView:tableView didHighlightRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView *)tableView didUnhighlightRowAtIndexPath:(NSIndexPath *)indexPath { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didUnhighlightRowAtIndexPath:)]) - [_delegate tableView:tableView didUnhighlightRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didUnhighlightRowAtIndexPath:)]) + [self.delegate tableView:tableView didUnhighlightRowAtIndexPath:indexPath]; } - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willSelectRowAtIndexPath:)]) - return [_delegate tableView:tableView willSelectRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willSelectRowAtIndexPath:)]) + return [self.delegate tableView:tableView willSelectRowAtIndexPath:indexPath]; return indexPath; } @@ -502,15 +502,15 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) - return [_delegate tableView:tableView willDeselectRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) + return [self.delegate tableView:tableView willDeselectRowAtIndexPath:indexPath]; return indexPath; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; if ([item respondsToSelector:@selector(setSelectionHandler:)]) { RETableViewItem *actionItem = (RETableViewItem *)item; @@ -520,23 +520,23 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) - [_delegate tableView:tableView didSelectRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didSelectRowAtIndexPath:)]) + [self.delegate tableView:tableView didSelectRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]) - [_delegate tableView:tableView didDeselectRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]) + [self.delegate tableView:tableView didDeselectRowAtIndexPath:indexPath]; } // Editing - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (![item isKindOfClass:[RETableViewItem class]]) @@ -544,8 +544,8 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)]) - return [_delegate tableView:tableView editingStyleForRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:editingStyleForRowAtIndexPath:)]) + return [self.delegate tableView:tableView editingStyleForRowAtIndexPath:indexPath]; return item.editingStyle; } @@ -554,8 +554,8 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]) - return [_delegate tableView:tableView titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:titleForDeleteConfirmationButtonForRowAtIndexPath:)]) + return [self.delegate tableView:tableView titleForDeleteConfirmationButtonForRowAtIndexPath:indexPath]; return NSLocalizedString(@"Delete", @"Delete"); } @@ -564,8 +564,8 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:shouldIndentWhileEditingRowAtIndexPath:)]) - return [_delegate tableView:tableView shouldIndentWhileEditingRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:shouldIndentWhileEditingRowAtIndexPath:)]) + return [self.delegate tableView:tableView shouldIndentWhileEditingRowAtIndexPath:indexPath]; return YES; } @@ -574,23 +574,23 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)]) - [_delegate tableView:tableView willBeginEditingRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:willBeginEditingRowAtIndexPath:)]) + [self.delegate tableView:tableView willBeginEditingRowAtIndexPath:indexPath]; } - (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)]) - [_delegate tableView:tableView didEndEditingRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:didEndEditingRowAtIndexPath:)]) + [self.delegate tableView:tableView didEndEditingRowAtIndexPath:indexPath]; } // Moving/reordering - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { - RETableViewSection *sourceSection = [_sections objectAtIndex:sourceIndexPath.section]; + RETableViewSection *sourceSection = [self.sections objectAtIndex:sourceIndexPath.section]; RETableViewItem *item = [sourceSection.items objectAtIndex:sourceIndexPath.row]; if (item.moveHandler) { BOOL allowed = item.moveHandler(item, sourceIndexPath, proposedDestinationIndexPath); @@ -600,8 +600,8 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:)]) - return [_delegate tableView:tableView targetIndexPathForMoveFromRowAtIndexPath:sourceIndexPath toProposedIndexPath:proposedDestinationIndexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:targetIndexPathForMoveFromRowAtIndexPath:toProposedIndexPath:)]) + return [self.delegate tableView:tableView targetIndexPathForMoveFromRowAtIndexPath:sourceIndexPath toProposedIndexPath:proposedDestinationIndexPath]; return proposedDestinationIndexPath; } @@ -612,8 +612,8 @@ BOOL REDeviceIsUIKit7() { { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:indentationLevelForRowAtIndexPath:)]) - return [_delegate tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:indentationLevelForRowAtIndexPath:)]) + return [self.delegate tableView:tableView indentationLevelForRowAtIndexPath:indexPath]; return 0; } @@ -622,7 +622,7 @@ BOOL REDeviceIsUIKit7() { - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; id anItem = [section.items objectAtIndex:indexPath.row]; if ([anItem respondsToSelector:@selector(setCopyHandler:)]) { RETableViewItem *item = anItem; @@ -632,15 +632,15 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:shouldShowMenuForRowAtIndexPath:)]) - return [_delegate tableView:tableView shouldShowMenuForRowAtIndexPath:indexPath]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:shouldShowMenuForRowAtIndexPath:)]) + return [self.delegate tableView:tableView shouldShowMenuForRowAtIndexPath:indexPath]; return NO; } - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; id anItem = [section.items objectAtIndex:indexPath.row]; if ([anItem respondsToSelector:@selector(setCopyHandler:)]) { RETableViewItem *item = anItem; @@ -656,15 +656,15 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableViewDelegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:canPerformAction:forRowAtIndexPath:withSender:)]) - return [_delegate tableView:tableView canPerformAction:action forRowAtIndexPath:indexPath withSender:sender]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:canPerformAction:forRowAtIndexPath:withSender:)]) + return [self.delegate tableView:tableView canPerformAction:action forRowAtIndexPath:indexPath withSender:sender]; return NO; } - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - RETableViewSection *section = [_sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (action == @selector(copy:)) { @@ -684,8 +684,8 @@ BOOL REDeviceIsUIKit7() { // Forward to UITableView delegate // - if ([_delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [_delegate respondsToSelector:@selector(tableView:performAction:forRowAtIndexPath:withSender:)]) - [_delegate tableView:tableView performAction:action forRowAtIndexPath:indexPath withSender:sender]; + if ([self.delegate conformsToProtocol:@protocol(UITableViewDelegate)] && [self.delegate respondsToSelector:@selector(tableView:performAction:forRowAtIndexPath:withSender:)]) + [self.delegate tableView:tableView performAction:action forRowAtIndexPath:indexPath withSender:sender]; } #pragma mark - @@ -695,72 +695,72 @@ BOOL REDeviceIsUIKit7() { { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidScroll:)]) - [_delegate scrollViewDidScroll:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidScroll:)]) + [self.delegate scrollViewDidScroll:self.tableView]; } - (void)scrollViewDidZoom:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidZoom:)]) - [_delegate scrollViewDidZoom:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidZoom:)]) + [self.delegate scrollViewDidZoom:self.tableView]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) - [_delegate scrollViewWillBeginDragging:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewWillBeginDragging:)]) + [self.delegate scrollViewWillBeginDragging:self.tableView]; } - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) - [_delegate scrollViewWillEndDragging:self.tableView withVelocity:velocity targetContentOffset:targetContentOffset]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewWillEndDragging:withVelocity:targetContentOffset:)]) + [self.delegate scrollViewWillEndDragging:self.tableView withVelocity:velocity targetContentOffset:targetContentOffset]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) - [_delegate scrollViewDidEndDragging:self.tableView willDecelerate:decelerate]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) + [self.delegate scrollViewDidEndDragging:self.tableView willDecelerate:decelerate]; } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) - [_delegate scrollViewWillBeginDecelerating:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewWillBeginDecelerating:)]) + [self.delegate scrollViewWillBeginDecelerating:self.tableView]; } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) - [_delegate scrollViewDidEndDecelerating:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidEndDecelerating:)]) + [self.delegate scrollViewDidEndDecelerating:self.tableView]; } - (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) - [_delegate scrollViewDidEndScrollingAnimation:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidEndScrollingAnimation:)]) + [self.delegate scrollViewDidEndScrollingAnimation:self.tableView]; } - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(viewForZoomingInScrollView:)]) - return [_delegate viewForZoomingInScrollView:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(viewForZoomingInScrollView:)]) + return [self.delegate viewForZoomingInScrollView:self.tableView]; return nil; } @@ -769,24 +769,24 @@ BOOL REDeviceIsUIKit7() { { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) - [_delegate scrollViewWillBeginZooming:self.tableView withView:view]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewWillBeginZooming:withView:)]) + [self.delegate scrollViewWillBeginZooming:self.tableView withView:view]; } - (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) - [_delegate scrollViewDidEndZooming:self.tableView withView:view atScale:scale]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidEndZooming:withView:atScale:)]) + [self.delegate scrollViewDidEndZooming:self.tableView withView:view atScale:scale]; } - (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) - return [_delegate scrollViewShouldScrollToTop:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewShouldScrollToTop:)]) + return [self.delegate scrollViewShouldScrollToTop:self.tableView]; return YES; } @@ -794,8 +794,8 @@ BOOL REDeviceIsUIKit7() { { // Forward to UIScrollView delegate // - if ([_delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [_delegate respondsToSelector:@selector(scrollViewDidScrollToTop:)]) - [_delegate scrollViewDidScrollToTop:self.tableView]; + if ([self.delegate conformsToProtocol:@protocol(UIScrollViewDelegate)] && [self.delegate respondsToSelector:@selector(scrollViewDidScrollToTop:)]) + [self.delegate scrollViewDidScrollToTop:self.tableView]; } #pragma mark - @@ -804,83 +804,83 @@ BOOL REDeviceIsUIKit7() { - (void)addSection:(RETableViewSection *)section { section.tableViewManager = self; - [_sections addObject:section]; + [self.sections addObject:section]; } - (void)addSectionsFromArray:(NSArray *)array { for (RETableViewSection *section in array) section.tableViewManager = self; - [_sections addObjectsFromArray:array]; + [self.sections addObjectsFromArray:array]; } - (void)insertSection:(RETableViewSection *)section atIndex:(NSUInteger)index { section.tableViewManager = self; - [_sections insertObject:section atIndex:index]; + [self.sections insertObject:section atIndex:index]; } - (void)insertSections:(NSArray *)sections atIndexes:(NSIndexSet *)indexes { for (RETableViewSection *section in sections) section.tableViewManager = self; - [_sections insertObjects:sections atIndexes:indexes]; + [self.sections insertObjects:sections atIndexes:indexes]; } - (void)removeSection:(RETableViewSection *)section { - [_sections removeObject:section]; + [self.sections removeObject:section]; } - (void)removeAllSections { - [_sections removeAllObjects]; + [self.sections removeAllObjects]; } - (void)removeSectionIdenticalTo:(RETableViewSection *)section inRange:(NSRange)range { - [_sections removeObjectIdenticalTo:section inRange:range]; + [self.sections removeObjectIdenticalTo:section inRange:range]; } - (void)removeSectionIdenticalTo:(RETableViewSection *)section { - [_sections removeObjectIdenticalTo:section]; + [self.sections removeObjectIdenticalTo:section]; } - (void)removeSectionsInArray:(NSArray *)otherArray { - [_sections removeObjectsInArray:otherArray]; + [self.sections removeObjectsInArray:otherArray]; } - (void)removeSectionsInRange:(NSRange)range { - [_sections removeObjectsInRange:range]; + [self.sections removeObjectsInRange:range]; } - (void)removeSection:(RETableViewSection *)section inRange:(NSRange)range { - [_sections removeObject:section inRange:range]; + [self.sections removeObject:section inRange:range]; } - (void)removeLastSection { - [_sections removeLastObject]; + [self.sections removeLastObject]; } - (void)removeSectionAtIndex:(NSUInteger)index { - [_sections removeObjectAtIndex:index]; + [self.sections removeObjectAtIndex:index]; } - (void)removeSectionsAtIndexes:(NSIndexSet *)indexes { - [_sections removeObjectsAtIndexes:indexes]; + [self.sections removeObjectsAtIndexes:indexes]; } - (void)replaceSectionAtIndex:(NSUInteger)index withSection:(RETableViewSection *)section { section.tableViewManager = self; - [_sections replaceObjectAtIndex:index withObject:section]; + [self.sections replaceObjectAtIndex:index withObject:section]; } - (void)replaceSectionsWithSectionsFromArray:(NSArray *)otherArray @@ -893,34 +893,34 @@ BOOL REDeviceIsUIKit7() { { for (RETableViewSection *section in sections) section.tableViewManager = self; - [_sections replaceObjectsAtIndexes:indexes withObjects:sections]; + [self.sections replaceObjectsAtIndexes:indexes withObjects:sections]; } - (void)replaceSectionsInRange:(NSRange)range withSectionsFromArray:(NSArray *)otherArray range:(NSRange)otherRange { for (RETableViewSection *section in otherArray) section.tableViewManager = self; - [_sections replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; + [self.sections replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; } - (void)replaceSectionsInRange:(NSRange)range withSectionsFromArray:(NSArray *)otherArray { - [_sections replaceObjectsInRange:range withObjectsFromArray:otherArray]; + [self.sections replaceObjectsInRange:range withObjectsFromArray:otherArray]; } - (void)exchangeSectionAtIndex:(NSUInteger)idx1 withSectionAtIndex:(NSUInteger)idx2 { - [_sections exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; + [self.sections exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; } - (void)sortSectionsUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context { - [_sections sortUsingFunction:compare context:context]; + [self.sections sortUsingFunction:compare context:context]; } - (void)sortSectionsUsingSelector:(SEL)comparator { - [_sections sortUsingSelector:comparator]; + [self.sections sortUsingSelector:comparator]; } #pragma mark - From 4e78dafccaf4e4117d165fadfb470c6ff2708a81 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 11:02:05 -0500 Subject: [PATCH 34/44] Use properties instead of iVars in RETableViewOptionsController.m --- RETableViewManager/RETableViewOptionsController.m | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/RETableViewManager/RETableViewOptionsController.m b/RETableViewManager/RETableViewOptionsController.m index c6a7028..d4c51d8 100644 --- a/RETableViewManager/RETableViewOptionsController.m +++ b/RETableViewManager/RETableViewOptionsController.m @@ -28,6 +28,9 @@ @interface RETableViewOptionsController () +@property (strong, readwrite, nonatomic) RETableViewManager *tableViewManager; +@property (strong, readwrite, nonatomic) RETableViewSection *mainSection; + @end @implementation RETableViewOptionsController @@ -51,12 +54,12 @@ { [super viewDidLoad]; - _tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView delegate:self.delegate]; - _mainSection = [[RETableViewSection alloc] init]; - [_tableViewManager addSection:_mainSection]; + self.tableViewManager = [[RETableViewManager alloc] initWithTableView:self.tableView delegate:self.delegate]; + self.mainSection = [[RETableViewSection alloc] init]; + [self.tableViewManager addSection:self.mainSection]; if (self.style) - _tableViewManager.style = self.style; + self.tableViewManager.style = self.style; __typeof (&*self) __weak weakSelf = self; void (^refreshItems)(void) = ^{ @@ -84,7 +87,7 @@ } } } - [_mainSection addItem:[RETableViewItem itemWithTitle:title accessoryType:accessoryType selectionHandler:^(RETableViewItem *selectedItem) { + [self.mainSection addItem:[RETableViewItem itemWithTitle:title accessoryType:accessoryType selectionHandler:^(RETableViewItem *selectedItem) { UITableViewCell *cell = [weakSelf.tableView cellForRowAtIndexPath:selectedItem.indexPath]; if (!weakSelf.multipleChoice) { for (NSIndexPath *indexPath in [weakSelf.tableView indexPathsForVisibleRows]) { From 06aa09d4689e8e834c3e2bf28257d81bd47c3bcf Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 11:03:50 -0500 Subject: [PATCH 35/44] Use properties instead of iVars in RETableViewSection.m --- RETableViewManager/RETableViewSection.m | 44 ++++++++++++------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/RETableViewManager/RETableViewSection.m b/RETableViewManager/RETableViewSection.m index eb322b6..3461429 100644 --- a/RETableViewManager/RETableViewSection.m +++ b/RETableViewManager/RETableViewSection.m @@ -62,7 +62,7 @@ if (!self) return nil; - _items = [[NSMutableArray alloc] init]; + self.items = [[NSMutableArray alloc] init]; return self; } @@ -138,7 +138,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items addObject:item]; + [self.items addObject:item]; } - (void)addItemsFromArray:(NSArray *)array @@ -147,7 +147,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items addObjectsFromArray:array]; + [self.items addObjectsFromArray:array]; } - (void)insertItem:(id)item atIndex:(NSUInteger)index @@ -155,7 +155,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items insertObject:item atIndex:index]; + [self.items insertObject:item atIndex:index]; } - (void)insertItems:(NSArray *)items atIndexes:(NSIndexSet *)indexes @@ -164,57 +164,57 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items insertObjects:items atIndexes:indexes]; + [self.items insertObjects:items atIndexes:indexes]; } - (void)removeItem:(id)item inRange:(NSRange)range { - [_items removeObject:item inRange:range]; + [self.items removeObject:item inRange:range]; } - (void)removeLastItem { - [_items removeLastObject]; + [self.items removeLastObject]; } - (void)removeItemAtIndex:(NSUInteger)index { - [_items removeObjectAtIndex:index]; + [self.items removeObjectAtIndex:index]; } - (void)removeItem:(id)item { - [_items removeObject:item]; + [self.items removeObject:item]; } - (void)removeAllItems { - [_items removeAllObjects]; + [self.items removeAllObjects]; } - (void)removeItemIdenticalTo:(id)item inRange:(NSRange)range { - [_items removeObjectIdenticalTo:item inRange:range]; + [self.items removeObjectIdenticalTo:item inRange:range]; } - (void)removeItemIdenticalTo:(id)item { - [_items removeObjectIdenticalTo:item]; + [self.items removeObjectIdenticalTo:item]; } - (void)removeItemsInArray:(NSArray *)otherArray { - [_items removeObjectsInArray:otherArray]; + [self.items removeObjectsInArray:otherArray]; } - (void)removeItemsInRange:(NSRange)range { - [_items removeObjectsInRange:range]; + [self.items removeObjectsInRange:range]; } - (void)removeItemsAtIndexes:(NSIndexSet *)indexes { - [_items removeObjectsAtIndexes:indexes]; + [self.items removeObjectsAtIndexes:indexes]; } - (void)replaceItemAtIndex:(NSUInteger)index withItem:(id)item @@ -222,7 +222,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items replaceObjectAtIndex:index withObject:item]; + [self.items replaceObjectAtIndex:index withObject:item]; } - (void)replaceItemsWithItemsFromArray:(NSArray *)otherArray @@ -237,7 +237,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; + [self.items replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; } - (void)replaceItemsInRange:(NSRange)range withItemsFromArray:(NSArray *)otherArray @@ -246,7 +246,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items replaceObjectsInRange:range withObjectsFromArray:otherArray]; + [self.items replaceObjectsInRange:range withObjectsFromArray:otherArray]; } - (void)replaceItemsAtIndexes:(NSIndexSet *)indexes withItems:(NSArray *)items @@ -255,22 +255,22 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [_items replaceObjectsAtIndexes:indexes withObjects:items]; + [self.items replaceObjectsAtIndexes:indexes withObjects:items]; } - (void)exchangeItemAtIndex:(NSUInteger)idx1 withItemAtIndex:(NSUInteger)idx2 { - [_items exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; + [self.items exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; } - (void)sortItemsUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context { - [_items sortUsingFunction:compare context:context]; + [self.items sortUsingFunction:compare context:context]; } - (void)sortItemsUsingSelector:(SEL)comparator { - [_items sortUsingSelector:comparator]; + [self.items sortUsingSelector:comparator]; } #pragma mark - From bbe1f5ce0c20ea22f5fb2cf57d315ca287b4588d Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 11:12:51 -0500 Subject: [PATCH 36/44] Return readonly and immutable NSArray of sections --- RETableViewManager/RETableViewManager.h | 2 +- RETableViewManager/RETableViewManager.m | 104 +++++++++++++----------- 2 files changed, 56 insertions(+), 50 deletions(-) diff --git a/RETableViewManager/RETableViewManager.h b/RETableViewManager/RETableViewManager.h index f0f9842..9365078 100644 --- a/RETableViewManager/RETableViewManager.h +++ b/RETableViewManager/RETableViewManager.h @@ -70,7 +70,7 @@ BOOL REDeviceIsUIKit7(); /** The array of sections. See RETableViewSection reference for details. */ -@property (strong, readwrite, nonatomic) NSMutableArray *sections; +@property (strong, readonly, nonatomic) NSArray *sections; /** The `UITableView` that needs to be managed using this `RETableViewManager`. diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index b286a42..6701075 100755 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -49,6 +49,7 @@ BOOL REDeviceIsUIKit7() { The array of pairs of items / cell classes. */ @property (strong, readwrite, nonatomic) NSMutableDictionary *registeredXIBs; +@property (strong, readwrite, nonatomic) NSMutableArray *mutableSections; @end @@ -88,7 +89,7 @@ BOOL REDeviceIsUIKit7() { self.tableView = tableView; - self.sections = [[NSMutableArray alloc] init]; + self.mutableSections = [[NSMutableArray alloc] init]; self.registeredClasses = [[NSMutableDictionary alloc] init]; self.registeredXIBs = [[NSMutableDictionary alloc] init]; self.style = [[RETableViewCellStyle alloc] init]; @@ -141,7 +142,7 @@ BOOL REDeviceIsUIKit7() { - (Class)classForCellAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; NSObject *item = [section.items objectAtIndex:indexPath.row]; Class cellClass; for (NSString *className in self.registeredClasses) { @@ -154,22 +155,27 @@ BOOL REDeviceIsUIKit7() { return cellClass; } +- (NSArray *)sections +{ + return self.mutableSections; +} + #pragma mark - #pragma mark Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return self.sections.count; + return self.mutableSections.count; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)sectionIndex { - return ((RETableViewSection *)[self.sections objectAtIndex:sectionIndex]).items.count; + return ((RETableViewSection *)[self.mutableSections objectAtIndex:sectionIndex]).items.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; UITableViewCellStyle cellStyle = UITableViewCellStyleDefault; @@ -233,14 +239,14 @@ BOOL REDeviceIsUIKit7() { - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView { NSMutableArray *titles; - for (RETableViewSection *section in self.sections) { + for (RETableViewSection *section in self.mutableSections) { if (section.indexTitle) { titles = [NSMutableArray array]; break; } } if (titles) { - for (RETableViewSection *section in self.sections) { + for (RETableViewSection *section in self.mutableSections) { [titles addObject:section.indexTitle ? section.indexTitle : @""]; } } @@ -250,23 +256,23 @@ BOOL REDeviceIsUIKit7() { - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; return section.headerTitle; } - (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; return section.footerTitle; } - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { - RETableViewSection *sourceSection = [self.sections objectAtIndex:sourceIndexPath.section]; + RETableViewSection *sourceSection = [self.mutableSections objectAtIndex:sourceIndexPath.section]; RETableViewItem *item = [sourceSection.items objectAtIndex:sourceIndexPath.row]; [sourceSection removeItemAtIndex:sourceIndexPath.row]; - RETableViewSection *destinationSection = [self.sections objectAtIndex:destinationIndexPath.section]; + RETableViewSection *destinationSection = [self.mutableSections objectAtIndex:destinationIndexPath.section]; [destinationSection insertItem:item atIndex:destinationIndexPath.row]; if (item.moveCompletionHandler) @@ -275,14 +281,14 @@ BOOL REDeviceIsUIKit7() { - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; return item.moveHandler != nil; } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if ([item isKindOfClass:[RETableViewItem class]]) { return item.editingStyle != UITableViewCellEditingStyleNone || item.moveHandler; @@ -294,7 +300,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (item.deletionHandlerWithCompletion) { item.deletionHandlerWithCompletion(item, ^{ @@ -310,7 +316,7 @@ BOOL REDeviceIsUIKit7() { } if (editingStyle == UITableViewCellEditingStyleInsert) { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (item.insertionHandler) item.insertionHandler(item); @@ -377,7 +383,7 @@ BOOL REDeviceIsUIKit7() { - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; // Forward to UITableView delegate @@ -390,7 +396,7 @@ BOOL REDeviceIsUIKit7() { - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; if (section.headerView) return section.headerView.frame.size.height; @@ -404,7 +410,7 @@ BOOL REDeviceIsUIKit7() { - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; if (section.footerView) return section.footerView.frame.size.height; @@ -420,7 +426,7 @@ BOOL REDeviceIsUIKit7() { - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; // Forward to UITableView delegate // @@ -432,7 +438,7 @@ BOOL REDeviceIsUIKit7() { - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)sectionIndex { - RETableViewSection *section = [self.sections objectAtIndex:sectionIndex]; + RETableViewSection *section = [self.mutableSections objectAtIndex:sectionIndex]; // Forward to UITableView delegate // @@ -446,7 +452,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; if ([item respondsToSelector:@selector(setAccessoryButtonTapHandler:)]) { RETableViewItem *actionItem = (RETableViewItem *)item; @@ -510,7 +516,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; id item = [section.items objectAtIndex:indexPath.row]; if ([item respondsToSelector:@selector(setSelectionHandler:)]) { RETableViewItem *actionItem = (RETableViewItem *)item; @@ -536,7 +542,7 @@ BOOL REDeviceIsUIKit7() { - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (![item isKindOfClass:[RETableViewItem class]]) @@ -590,7 +596,7 @@ BOOL REDeviceIsUIKit7() { - (NSIndexPath *)tableView:(UITableView *)tableView targetIndexPathForMoveFromRowAtIndexPath:(NSIndexPath *)sourceIndexPath toProposedIndexPath:(NSIndexPath *)proposedDestinationIndexPath { - RETableViewSection *sourceSection = [self.sections objectAtIndex:sourceIndexPath.section]; + RETableViewSection *sourceSection = [self.mutableSections objectAtIndex:sourceIndexPath.section]; RETableViewItem *item = [sourceSection.items objectAtIndex:sourceIndexPath.row]; if (item.moveHandler) { BOOL allowed = item.moveHandler(item, sourceIndexPath, proposedDestinationIndexPath); @@ -622,7 +628,7 @@ BOOL REDeviceIsUIKit7() { - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; id anItem = [section.items objectAtIndex:indexPath.row]; if ([anItem respondsToSelector:@selector(setCopyHandler:)]) { RETableViewItem *item = anItem; @@ -640,7 +646,7 @@ BOOL REDeviceIsUIKit7() { - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; id anItem = [section.items objectAtIndex:indexPath.row]; if ([anItem respondsToSelector:@selector(setCopyHandler:)]) { RETableViewItem *item = anItem; @@ -664,7 +670,7 @@ BOOL REDeviceIsUIKit7() { - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { - RETableViewSection *section = [self.sections objectAtIndex:indexPath.section]; + RETableViewSection *section = [self.mutableSections objectAtIndex:indexPath.section]; RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (action == @selector(copy:)) { @@ -804,83 +810,83 @@ BOOL REDeviceIsUIKit7() { - (void)addSection:(RETableViewSection *)section { section.tableViewManager = self; - [self.sections addObject:section]; + [self.mutableSections addObject:section]; } - (void)addSectionsFromArray:(NSArray *)array { for (RETableViewSection *section in array) section.tableViewManager = self; - [self.sections addObjectsFromArray:array]; + [self.mutableSections addObjectsFromArray:array]; } - (void)insertSection:(RETableViewSection *)section atIndex:(NSUInteger)index { section.tableViewManager = self; - [self.sections insertObject:section atIndex:index]; + [self.mutableSections insertObject:section atIndex:index]; } - (void)insertSections:(NSArray *)sections atIndexes:(NSIndexSet *)indexes { for (RETableViewSection *section in sections) section.tableViewManager = self; - [self.sections insertObjects:sections atIndexes:indexes]; + [self.mutableSections insertObjects:sections atIndexes:indexes]; } - (void)removeSection:(RETableViewSection *)section { - [self.sections removeObject:section]; + [self.mutableSections removeObject:section]; } - (void)removeAllSections { - [self.sections removeAllObjects]; + [self.mutableSections removeAllObjects]; } - (void)removeSectionIdenticalTo:(RETableViewSection *)section inRange:(NSRange)range { - [self.sections removeObjectIdenticalTo:section inRange:range]; + [self.mutableSections removeObjectIdenticalTo:section inRange:range]; } - (void)removeSectionIdenticalTo:(RETableViewSection *)section { - [self.sections removeObjectIdenticalTo:section]; + [self.mutableSections removeObjectIdenticalTo:section]; } - (void)removeSectionsInArray:(NSArray *)otherArray { - [self.sections removeObjectsInArray:otherArray]; + [self.mutableSections removeObjectsInArray:otherArray]; } - (void)removeSectionsInRange:(NSRange)range { - [self.sections removeObjectsInRange:range]; + [self.mutableSections removeObjectsInRange:range]; } - (void)removeSection:(RETableViewSection *)section inRange:(NSRange)range { - [self.sections removeObject:section inRange:range]; + [self.mutableSections removeObject:section inRange:range]; } - (void)removeLastSection { - [self.sections removeLastObject]; + [self.mutableSections removeLastObject]; } - (void)removeSectionAtIndex:(NSUInteger)index { - [self.sections removeObjectAtIndex:index]; + [self.mutableSections removeObjectAtIndex:index]; } - (void)removeSectionsAtIndexes:(NSIndexSet *)indexes { - [self.sections removeObjectsAtIndexes:indexes]; + [self.mutableSections removeObjectsAtIndexes:indexes]; } - (void)replaceSectionAtIndex:(NSUInteger)index withSection:(RETableViewSection *)section { section.tableViewManager = self; - [self.sections replaceObjectAtIndex:index withObject:section]; + [self.mutableSections replaceObjectAtIndex:index withObject:section]; } - (void)replaceSectionsWithSectionsFromArray:(NSArray *)otherArray @@ -893,34 +899,34 @@ BOOL REDeviceIsUIKit7() { { for (RETableViewSection *section in sections) section.tableViewManager = self; - [self.sections replaceObjectsAtIndexes:indexes withObjects:sections]; + [self.mutableSections replaceObjectsAtIndexes:indexes withObjects:sections]; } - (void)replaceSectionsInRange:(NSRange)range withSectionsFromArray:(NSArray *)otherArray range:(NSRange)otherRange { for (RETableViewSection *section in otherArray) section.tableViewManager = self; - [self.sections replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; + [self.mutableSections replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; } - (void)replaceSectionsInRange:(NSRange)range withSectionsFromArray:(NSArray *)otherArray { - [self.sections replaceObjectsInRange:range withObjectsFromArray:otherArray]; + [self.mutableSections replaceObjectsInRange:range withObjectsFromArray:otherArray]; } - (void)exchangeSectionAtIndex:(NSUInteger)idx1 withSectionAtIndex:(NSUInteger)idx2 { - [self.sections exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; + [self.mutableSections exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; } - (void)sortSectionsUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context { - [self.sections sortUsingFunction:compare context:context]; + [self.mutableSections sortUsingFunction:compare context:context]; } - (void)sortSectionsUsingSelector:(SEL)comparator { - [self.sections sortUsingSelector:comparator]; + [self.mutableSections sortUsingSelector:comparator]; } #pragma mark - @@ -929,7 +935,7 @@ BOOL REDeviceIsUIKit7() { - (NSArray *)errors { NSMutableArray *errors; - for (RETableViewSection *section in self.sections) { + for (RETableViewSection *section in self.mutableSections) { if (section.errors) { if (!errors) { errors = [[NSMutableArray alloc] init]; From 6dc99d271e7164eb1da8821080b6425c5f3b962d Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 11:22:43 -0500 Subject: [PATCH 37/44] Hide mutable items from interface declaration --- RETableViewManager/RETableViewManager.m | 4 +- RETableViewManager/RETableViewSection.h | 2 +- RETableViewManager/RETableViewSection.m | 59 +++++++++++++++---------- 3 files changed, 38 insertions(+), 27 deletions(-) diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 6701075..61babd2 100755 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -304,13 +304,13 @@ BOOL REDeviceIsUIKit7() { RETableViewItem *item = [section.items objectAtIndex:indexPath.row]; if (item.deletionHandlerWithCompletion) { item.deletionHandlerWithCompletion(item, ^{ - [section.items removeObjectAtIndex:indexPath.row]; + [section removeItemAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; }); } else { if (item.deletionHandler) item.deletionHandler(item); - [section.items removeObjectAtIndex:indexPath.row]; + [section removeItemAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic]; } } diff --git a/RETableViewManager/RETableViewSection.h b/RETableViewManager/RETableViewSection.h index f5d97af..5702df0 100644 --- a/RETableViewManager/RETableViewSection.h +++ b/RETableViewManager/RETableViewSection.h @@ -36,7 +36,7 @@ /** An array of section items (rows). */ -@property (strong, readwrite, nonatomic) NSMutableArray *items; +@property (strong, readonly, nonatomic) NSArray *items; /** The title of the header of the specified section of the table view. diff --git a/RETableViewManager/RETableViewSection.m b/RETableViewManager/RETableViewSection.m index 3461429..5a2d251 100644 --- a/RETableViewManager/RETableViewSection.m +++ b/RETableViewManager/RETableViewSection.m @@ -26,6 +26,12 @@ #import "RETableViewSection.h" #import "RETableViewManager.h" +@interface RETableViewSection () + +@property (strong, readwrite, nonatomic) NSMutableArray *mutableItems; + +@end + @implementation RETableViewSection #pragma mark - @@ -62,7 +68,7 @@ if (!self) return nil; - self.items = [[NSMutableArray alloc] init]; + self.mutableItems = [[NSMutableArray alloc] init]; return self; } @@ -121,7 +127,7 @@ - (CGFloat)maximumTitleWidthWithFont:(UIFont *)font { CGFloat width = 0; - for (RETableViewItem *item in self.items) { + for (RETableViewItem *item in self.mutableItems) { if ([item isMemberOfClass:[RETextItem class]] || [item isMemberOfClass:[REDateTimeItem class]] || [item isMemberOfClass:[RENumberItem class]]) { CGSize size = [item.title sizeWithFont:font]; width = MAX(width, size.width); @@ -133,12 +139,17 @@ #pragma mark - #pragma mark Managing items +- (NSArray *)items +{ + return self.mutableItems; +} + - (void)addItem:(id)item { if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items addObject:item]; + [self.mutableItems addObject:item]; } - (void)addItemsFromArray:(NSArray *)array @@ -147,7 +158,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items addObjectsFromArray:array]; + [self.mutableItems addObjectsFromArray:array]; } - (void)insertItem:(id)item atIndex:(NSUInteger)index @@ -155,7 +166,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items insertObject:item atIndex:index]; + [self.mutableItems insertObject:item atIndex:index]; } - (void)insertItems:(NSArray *)items atIndexes:(NSIndexSet *)indexes @@ -164,57 +175,57 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items insertObjects:items atIndexes:indexes]; + [self.mutableItems insertObjects:items atIndexes:indexes]; } - (void)removeItem:(id)item inRange:(NSRange)range { - [self.items removeObject:item inRange:range]; + [self.mutableItems removeObject:item inRange:range]; } - (void)removeLastItem { - [self.items removeLastObject]; + [self.mutableItems removeLastObject]; } - (void)removeItemAtIndex:(NSUInteger)index { - [self.items removeObjectAtIndex:index]; + [self.mutableItems removeObjectAtIndex:index]; } - (void)removeItem:(id)item { - [self.items removeObject:item]; + [self.mutableItems removeObject:item]; } - (void)removeAllItems { - [self.items removeAllObjects]; + [self.mutableItems removeAllObjects]; } - (void)removeItemIdenticalTo:(id)item inRange:(NSRange)range { - [self.items removeObjectIdenticalTo:item inRange:range]; + [self.mutableItems removeObjectIdenticalTo:item inRange:range]; } - (void)removeItemIdenticalTo:(id)item { - [self.items removeObjectIdenticalTo:item]; + [self.mutableItems removeObjectIdenticalTo:item]; } - (void)removeItemsInArray:(NSArray *)otherArray { - [self.items removeObjectsInArray:otherArray]; + [self.mutableItems removeObjectsInArray:otherArray]; } - (void)removeItemsInRange:(NSRange)range { - [self.items removeObjectsInRange:range]; + [self.mutableItems removeObjectsInRange:range]; } - (void)removeItemsAtIndexes:(NSIndexSet *)indexes { - [self.items removeObjectsAtIndexes:indexes]; + [self.mutableItems removeObjectsAtIndexes:indexes]; } - (void)replaceItemAtIndex:(NSUInteger)index withItem:(id)item @@ -222,7 +233,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items replaceObjectAtIndex:index withObject:item]; + [self.mutableItems replaceObjectAtIndex:index withObject:item]; } - (void)replaceItemsWithItemsFromArray:(NSArray *)otherArray @@ -237,7 +248,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; + [self.mutableItems replaceObjectsInRange:range withObjectsFromArray:otherArray range:otherRange]; } - (void)replaceItemsInRange:(NSRange)range withItemsFromArray:(NSArray *)otherArray @@ -246,7 +257,7 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items replaceObjectsInRange:range withObjectsFromArray:otherArray]; + [self.mutableItems replaceObjectsInRange:range withObjectsFromArray:otherArray]; } - (void)replaceItemsAtIndexes:(NSIndexSet *)indexes withItems:(NSArray *)items @@ -255,22 +266,22 @@ if ([item isKindOfClass:[RETableViewItem class]]) ((RETableViewItem *)item).section = self; - [self.items replaceObjectsAtIndexes:indexes withObjects:items]; + [self.mutableItems replaceObjectsAtIndexes:indexes withObjects:items]; } - (void)exchangeItemAtIndex:(NSUInteger)idx1 withItemAtIndex:(NSUInteger)idx2 { - [self.items exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; + [self.mutableItems exchangeObjectAtIndex:idx1 withObjectAtIndex:idx2]; } - (void)sortItemsUsingFunction:(NSInteger (*)(id, id, void *))compare context:(void *)context { - [self.items sortUsingFunction:compare context:context]; + [self.mutableItems sortUsingFunction:compare context:context]; } - (void)sortItemsUsingSelector:(SEL)comparator { - [self.items sortUsingSelector:comparator]; + [self.mutableItems sortUsingSelector:comparator]; } #pragma mark - @@ -287,7 +298,7 @@ - (NSArray *)errors { NSMutableArray *errors; - for (RETableViewItem *item in self.items) { + for (RETableViewItem *item in self.mutableItems) { if ([item respondsToSelector:@selector(errors)] && item.errors) { if (!errors) { errors = [[NSMutableArray alloc] init]; From 93c3cb1f8c86fe5f83af91ca299439d2f82292f2 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Wed, 4 Sep 2013 12:05:56 -0500 Subject: [PATCH 38/44] Update dependency --- RETableViewManager.podspec | 2 +- .../Vendor/REValidation/REValidation.m | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index 5166486..cba7941 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -17,5 +17,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '6.0' s.dependency 'REFormattedNumberField', '~> 1.0.4' - s.dependency 'REValidation', '~> 0.1.1' + s.dependency 'REValidation', '~> 0.1.2' end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.m b/RETableViewManagerExample/Vendor/REValidation/REValidation.m index 47c48d2..4a5309a 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.m @@ -52,19 +52,18 @@ + (void)registerDefaultValidators { - static BOOL registeredValidators; - if (!registeredValidators) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ [REValidation registerValidator:[REPresenceValidator class]]; [REValidation registerValidator:[RELengthValidator class]]; [REValidation registerValidator:[REEmailValidator class]]; - registeredValidators = YES; - } + }); } + (void)registerDefaultErrorMessages { - static BOOL registeredMessages; - if (!registeredMessages) { + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ NSDictionary *messages = @{ @"com.REValidation.presence": @"%@ can't be blank.", @"com.REValidation.minimumLength": @"%@ is too short (minimum is %i characters).", @@ -72,8 +71,7 @@ @"com.REValidation.email": @"%@ is not a valid email.", }; [REValidation sharedObject].errorMessages = [NSMutableDictionary dictionaryWithDictionary:messages]; - registeredMessages = YES; - } + }); } + (NSString *)errorMessageForDomain:(NSString *)domain From fc9e057b23e0274cb76ec4d76e1623e541d2f4c4 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 11:48:36 -0500 Subject: [PATCH 39/44] Add URL validation --- RETableViewManager/RETableViewManager.m | 5 +- RETableViewManager/RETableViewSection.m | 13 +++-- .../project.pbxproj | 6 +++ .../Controllers/ValidationsViewController.m | 10 +++- .../Vendor/REValidation/REValidation.h | 1 + .../Vendor/REValidation/REValidation.m | 3 ++ .../Validators/REEmailValidator.m | 3 ++ .../REValidation/Validators/REURLValidator.h | 30 +++++++++++ .../REValidation/Validators/REURLValidator.m | 51 +++++++++++++++++++ 9 files changed, 113 insertions(+), 9 deletions(-) create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.h create mode 100644 RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.m diff --git a/RETableViewManager/RETableViewManager.m b/RETableViewManager/RETableViewManager.m index 61babd2..d77cc55 100755 --- a/RETableViewManager/RETableViewManager.m +++ b/RETableViewManager/RETableViewManager.m @@ -936,11 +936,12 @@ BOOL REDeviceIsUIKit7() { { NSMutableArray *errors; for (RETableViewSection *section in self.mutableSections) { - if (section.errors) { + NSArray *sectionErrors = section.errors; + if (sectionErrors) { if (!errors) { errors = [[NSMutableArray alloc] init]; } - [errors addObjectsFromArray:section.errors]; + [errors addObjectsFromArray:sectionErrors]; } } return errors; diff --git a/RETableViewManager/RETableViewSection.m b/RETableViewManager/RETableViewSection.m index 5a2d251..a1ddc1c 100644 --- a/RETableViewManager/RETableViewSection.m +++ b/RETableViewManager/RETableViewSection.m @@ -299,12 +299,15 @@ { NSMutableArray *errors; for (RETableViewItem *item in self.mutableItems) { - if ([item respondsToSelector:@selector(errors)] && item.errors) { - if (!errors) { - errors = [[NSMutableArray alloc] init]; + if ([item respondsToSelector:@selector(errors)]) { + NSArray *itemErrors = item.errors; + if (itemErrors) { + if (!errors) { + errors = [[NSMutableArray alloc] init]; + } + if (itemErrors.count > 0) + [errors addObject:itemErrors[0]]; } - if (item.errors.count > 0) - [errors addObject:item.errors[0]]; } } return errors; diff --git a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj index 0160865..ffcce23 100644 --- a/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj +++ b/RETableViewManagerExample/RETableViewManagerExample.xcodeproj/project.pbxproj @@ -46,6 +46,7 @@ 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */; }; 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */; }; 30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00D7917C667A90010D439 /* ValidationsViewController.m */; }; + 30B00DEE17D8E9CE0010D439 /* REURLValidator.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B00DED17D8E90D0010D439 /* REURLValidator.m */; }; 30D1C7D617AC08F4001F731C /* First_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */; }; 30D1C7D717AC08F4001F731C /* Last_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */; }; 30D1C7D817AC08F4001F731C /* Middle_Alt@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */; }; @@ -156,6 +157,8 @@ 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = REPresenceValidator.m; sourceTree = ""; }; 30B00D7817C667A90010D439 /* ValidationsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ValidationsViewController.h; sourceTree = ""; }; 30B00D7917C667A90010D439 /* ValidationsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ValidationsViewController.m; sourceTree = ""; }; + 30B00DEC17D8E90D0010D439 /* REURLValidator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = REURLValidator.h; sourceTree = ""; }; + 30B00DED17D8E90D0010D439 /* REURLValidator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = REURLValidator.m; sourceTree = ""; }; 30D1C7D217AC08F3001F731C /* First_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "First_Alt@2x.png"; path = "Resources/First_Alt@2x.png"; sourceTree = ""; }; 30D1C7D317AC08F3001F731C /* Last_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Last_Alt@2x.png"; path = "Resources/Last_Alt@2x.png"; sourceTree = ""; }; 30D1C7D417AC08F3001F731C /* Middle_Alt@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "Middle_Alt@2x.png"; path = "Resources/Middle_Alt@2x.png"; sourceTree = ""; }; @@ -362,6 +365,8 @@ 30B00D5B17C56EEF0010D439 /* RELengthValidator.m */, 30B00D5C17C56EEF0010D439 /* REPresenceValidator.h */, 30B00D5D17C56EEF0010D439 /* REPresenceValidator.m */, + 30B00DEC17D8E90D0010D439 /* REURLValidator.h */, + 30B00DED17D8E90D0010D439 /* REURLValidator.m */, ); path = Validators; sourceTree = ""; @@ -648,6 +653,7 @@ 30B00D5F17C56EEF0010D439 /* REValidation.m in Sources */, 30B00D6017C56EEF0010D439 /* REValidator.m in Sources */, 30B00D6117C56EEF0010D439 /* REEmailValidator.m in Sources */, + 30B00DEE17D8E9CE0010D439 /* REURLValidator.m in Sources */, 30B00D6217C56EEF0010D439 /* RELengthValidator.m in Sources */, 30B00D6317C56EEF0010D439 /* REPresenceValidator.m in Sources */, 30B00D7A17C667A90010D439 /* ValidationsViewController.m in Sources */, diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m index 3b85b32..17917ea 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m @@ -12,6 +12,7 @@ @property (strong, readwrite, nonatomic) RETextItem *textItem; @property (strong, readwrite, nonatomic) RETextItem *emailItem; +@property (strong, readwrite, nonatomic) RETextItem *urlItem; @end @@ -43,8 +44,12 @@ self.emailItem.autocapitalizationType = UITextAutocapitalizationTypeNone; self.emailItem.validators = @[@"presence", @"email"]; + self.urlItem = [RETextItem itemWithTitle:@"URL" value:@"http://invalid-url.co%m" placeholder:@"URL item"]; + self.urlItem.validators = @[@"url"]; + [section addItem:self.textItem]; [section addItem:self.emailItem]; + [section addItem:self.urlItem]; } #pragma mark - @@ -52,9 +57,10 @@ - (void)validateButtonPressed:(UIButton *)sender { - if (self.manager.errors.count > 0) { + NSArray *managerErrors = self.manager.errors; + if (managerErrors.count > 0) { NSMutableArray *errors = [NSMutableArray array]; - for (NSError *error in self.manager.errors) { + for (NSError *error in managerErrors) { [errors addObject:error.localizedDescription]; } NSString *errorString = [errors componentsJoinedByString:@"\n"]; diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.h b/RETableViewManagerExample/Vendor/REValidation/REValidation.h index 8aefa97..a2c2d61 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.h +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.h @@ -29,6 +29,7 @@ #import "REPresenceValidator.h" #import "RELengthValidator.h" #import "REEmailValidator.h" +#import "REURLValidator.h" @interface REValidation : NSObject diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.m b/RETableViewManagerExample/Vendor/REValidation/REValidation.m index 4a5309a..0502c57 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.m @@ -57,6 +57,7 @@ [REValidation registerValidator:[REPresenceValidator class]]; [REValidation registerValidator:[RELengthValidator class]]; [REValidation registerValidator:[REEmailValidator class]]; + [REValidation registerValidator:[REURLValidator class]]; }); } @@ -69,6 +70,7 @@ @"com.REValidation.minimumLength": @"%@ is too short (minimum is %i characters).", @"com.REValidation.maximumLength": @"%@ is too long (maximum is %i characters).", @"com.REValidation.email": @"%@ is not a valid email.", + @"com.REValidation.url": @"%@ is not a valid url." }; [REValidation sharedObject].errorMessages = [NSMutableDictionary dictionaryWithDictionary:messages]; }); @@ -91,6 +93,7 @@ + (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string { + NSLog(@"validate = %@, %@", name, string); NSString *validatorStringName = [string componentsSeparatedByString:@"("][0]; for (NSString *validatorName in [REValidation sharedObject].registeredValidators) { if ([validatorName isEqualToString:validatorStringName]) { diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m index 0c1ecda..56176af 100644 --- a/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REEmailValidator.m @@ -36,6 +36,9 @@ + (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters { NSString *string = object ? object : @""; + if (string.length == 0) + return nil; + NSError *error = NULL; NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}" options:NSRegularExpressionCaseInsensitive error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)]; diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.h b/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.h new file mode 100644 index 0000000..3990fd1 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.h @@ -0,0 +1,30 @@ +// +// REURLValidator.h +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REValidator.h" + +@interface REURLValidator : REValidator + +@end diff --git a/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.m b/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.m new file mode 100644 index 0000000..6954e38 --- /dev/null +++ b/RETableViewManagerExample/Vendor/REValidation/Validators/REURLValidator.m @@ -0,0 +1,51 @@ +// +// REURLValidator.m +// REValidation +// +// Copyright (c) 2013 Roman Efimov (https://github.com/romaonthego) +// +// 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 "REURLValidator.h" +#import "REValidation.h" + +@implementation REURLValidator + ++ (NSString *)name +{ + return @"url"; +} + ++ (NSError *)validateObject:(NSString *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters +{ + NSString *string = object ? object : @""; + if (string.length == 0) + return nil; + + NSError *error = NULL; + NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"^(?i)(?:(?:https?|ftp):\\/\\/)?(?:\\S+(?::\\S*)?@)?(?:(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:\\/[^\\s]*)?$" options:NSRegularExpressionCaseInsensitive error:&error]; + NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)]; + if (!match) + return [NSError re_validationErrorForDomain:@"com.REValidation.url", name]; + + return nil; +} + +@end From e0966330d17a27fc3f5cac8845441e9230ca0df3 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 11:49:24 -0500 Subject: [PATCH 40/44] Remove NSLog --- RETableViewManagerExample/Vendor/REValidation/REValidation.m | 1 - 1 file changed, 1 deletion(-) diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.m b/RETableViewManagerExample/Vendor/REValidation/REValidation.m index 0502c57..6da25d8 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.m @@ -93,7 +93,6 @@ + (NSError *)validateObject:(NSObject *)object name:(NSString *)name validatorString:(NSString *)string { - NSLog(@"validate = %@, %@", name, string); NSString *validatorStringName = [string componentsSeparatedByString:@"("][0]; for (NSString *validatorName in [REValidation sharedObject].registeredValidators) { if ([validatorName isEqualToString:validatorStringName]) { From 5032daac4b7d1f101b6b51f32bc4b7ccaeff1e34 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 11:58:51 -0500 Subject: [PATCH 41/44] Add inline validation example --- .../Controllers/ValidationsViewController.m | 14 ++++++++++++++ .../Vendor/REValidation/REValidation.m | 17 +++++++++++------ .../Vendor/REValidation/REValidator.h | 2 ++ .../Vendor/REValidation/REValidator.m | 7 +++++++ 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m index 17917ea..26723c9 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m @@ -13,6 +13,7 @@ @property (strong, readwrite, nonatomic) RETextItem *textItem; @property (strong, readwrite, nonatomic) RETextItem *emailItem; @property (strong, readwrite, nonatomic) RETextItem *urlItem; +@property (strong, readwrite, nonatomic) RETextItem *inlineTestItem; @end @@ -47,9 +48,22 @@ self.urlItem = [RETextItem itemWithTitle:@"URL" value:@"http://invalid-url.co%m" placeholder:@"URL item"]; self.urlItem.validators = @[@"url"]; + // Inline Validation Example + // + REValidator *nameValidator = [REValidator validator]; + nameValidator.inlineValidation = ^NSError *(NSString *string, NSString *name) { + if ([string componentsSeparatedByString:@" "].count < 2) { + return [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Please enter first and last name."}]; + } + return nil; + }; + self.inlineTestItem = [RETextItem itemWithTitle:@"Name" value:@"" placeholder:@"First & Last Name"]; + self.inlineTestItem.validators = @[nameValidator]; + [section addItem:self.textItem]; [section addItem:self.emailItem]; [section addItem:self.urlItem]; + [section addItem:self.inlineTestItem]; } #pragma mark - diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidation.m b/RETableViewManagerExample/Vendor/REValidation/REValidation.m index 6da25d8..ec2c939 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidation.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidation.m @@ -41,7 +41,7 @@ dispatch_once(&onceToken, ^{ _sharedClient = [[REValidation alloc] init]; }); - + return _sharedClient; } @@ -111,18 +111,23 @@ + (NSArray *)validateObject:(NSObject *)object name:(NSString *)name validators:(NSArray *)validators { NSMutableArray *errors = [NSMutableArray array]; - + for (id validator in validators) { NSError *error; if ([validator isKindOfClass:[NSString class]]) { error = [self validateObject:object name:name validatorString:(NSString *)validator]; } else { - error = [self validateObject:object name:name validator:validator]; + REValidator *v = (REValidator *)validator; + if (v.inlineValidation) { + error = [[v class] validateObject:object variableName:name validation:v.inlineValidation]; + } else { + error = [self validateObject:object name:name validator:validator]; + } } if (error) [errors addObject:error]; } - + return errors; } @@ -132,9 +137,9 @@ self = [super init]; if (!self) return nil; - + self.registeredValidators = [[NSMutableDictionary alloc] init]; - + return self; } diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.h b/RETableViewManagerExample/Vendor/REValidation/REValidator.h index 857a910..75834a1 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.h +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.h @@ -28,6 +28,7 @@ @interface REValidator : NSObject @property (strong, readonly, nonatomic) NSDictionary *parameters; +@property (copy, readwrite, nonatomic) NSError *(^inlineValidation)(id object, NSString *name); ///----------------------------- /// @name Getting Validator Instance @@ -48,5 +49,6 @@ ///----------------------------- + (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name parameters:(NSDictionary *)parameters; ++ (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name validation:(NSError *(^)(id object, NSString *name))validation; @end diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.m b/RETableViewManagerExample/Vendor/REValidation/REValidator.m index 55d01b5..7b10d59 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.m @@ -55,6 +55,13 @@ return nil; } ++ (NSError *)validateObject:(NSObject *)object variableName:(NSString *)name validation:(NSError *(^)(id object, NSString *name))validation +{ + if (validation) + return validation(object, name); + return nil; +} + + (NSDictionary *)parseParameterString:(NSString *)string { return nil; From 828190cd5f5f765ea6b1239c1d617a4aadafb61a Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 12:04:21 -0500 Subject: [PATCH 42/44] Update inline validation example --- .../Classes/Controllers/ValidationsViewController.m | 12 ++++++------ .../Vendor/REValidation/REValidator.h | 1 + .../Vendor/REValidation/REValidator.m | 11 +++++++++-- 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m index 26723c9..d8b549b 100644 --- a/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m +++ b/RETableViewManagerExample/RETableViewManagerExample/Classes/Controllers/ValidationsViewController.m @@ -50,15 +50,15 @@ // Inline Validation Example // - REValidator *nameValidator = [REValidator validator]; - nameValidator.inlineValidation = ^NSError *(NSString *string, NSString *name) { - if ([string componentsSeparatedByString:@" "].count < 2) { - return [NSError errorWithDomain:@"" code:0 userInfo:@{NSLocalizedDescriptionKey: @"Please enter first and last name."}]; + REValidator *nameValidator = [REValidator validatorWithInlineValidation:^NSError *(NSString *string, NSString *name) { + NSString *cleanString = [string stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]]; + if ([cleanString componentsSeparatedByString:@" "].count < 2) { + return [NSError errorWithDomain:@"" code:0 userInfo:@{ NSLocalizedDescriptionKey: @"Please enter first and last name." }]; } return nil; - }; + }]; self.inlineTestItem = [RETextItem itemWithTitle:@"Name" value:@"" placeholder:@"First & Last Name"]; - self.inlineTestItem.validators = @[nameValidator]; + self.inlineTestItem.validators = @[@"presence", nameValidator]; [section addItem:self.textItem]; [section addItem:self.emailItem]; diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.h b/RETableViewManagerExample/Vendor/REValidation/REValidator.h index 75834a1..7a3b1cc 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.h +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.h @@ -36,6 +36,7 @@ + (instancetype)validator; + (instancetype)validatorWithParameters:(NSDictionary *)parameters; ++ (instancetype)validatorWithInlineValidation:(NSError *(^)(id object, NSString *name))validation; ///----------------------------- /// @name Configuring Representation diff --git a/RETableViewManagerExample/Vendor/REValidation/REValidator.m b/RETableViewManagerExample/Vendor/REValidation/REValidator.m index 7b10d59..a0407f3 100644 --- a/RETableViewManagerExample/Vendor/REValidation/REValidator.m +++ b/RETableViewManagerExample/Vendor/REValidation/REValidator.m @@ -33,6 +33,11 @@ @implementation REValidator ++ (instancetype)validator +{ + return [[self alloc] init]; +} + + (instancetype)validatorWithParameters:(NSDictionary *)parameters { REValidator *validator = [[self alloc] init]; @@ -40,9 +45,11 @@ return validator; } -+ (instancetype)validator ++ (instancetype)validatorWithInlineValidation:(NSError *(^)(id object, NSString *name))validation { - return [[self alloc] init]; + REValidator *validator = [[self alloc] init]; + validator.inlineValidation = validation; + return validator; } + (NSString *)name From bddf4a919d6c878a395ac94771ed364ee3df5de7 Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 12:09:10 -0500 Subject: [PATCH 43/44] Version bump (1.2.5) --- README.md | 2 +- RETableViewManager.podspec | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index a190c0b..933539c 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ Edit your Podfile and add RETableViewManager: ``` bash platform :ios, '6.0' -pod 'RETableViewManager', '~> 1.2.4' +pod 'RETableViewManager', '~> 1.2.5' ``` Install into your Xcode project: diff --git a/RETableViewManager.podspec b/RETableViewManager.podspec index cba7941..8fe9d54 100644 --- a/RETableViewManager.podspec +++ b/RETableViewManager.podspec @@ -1,11 +1,11 @@ Pod::Spec.new do |s| s.name = 'RETableViewManager' - s.version = '1.2.4' + s.version = '1.2.5' s.authors = { 'Roman Efimov' => 'romefimov@gmail.com' } s.homepage = 'https://github.com/romaonthego/RETableViewManager' s.summary = 'Powerful data driven content manager for UITableView.' s.source = { :git => 'https://github.com/romaonthego/RETableViewManager.git', - :tag => '1.2.4' } + :tag => '1.2.5' } s.license = { :type => "MIT", :file => "LICENSE" } s.platform = :ios, '6.0' @@ -17,5 +17,5 @@ Pod::Spec.new do |s| s.ios.deployment_target = '6.0' s.dependency 'REFormattedNumberField', '~> 1.0.4' - s.dependency 'REValidation', '~> 0.1.2' + s.dependency 'REValidation', '~> 0.1.3' end From cf498c988433e4c7422c35299914359bb1abe8cd Mon Sep 17 00:00:00 2001 From: Roman Efimov Date: Thu, 5 Sep 2013 12:13:18 -0500 Subject: [PATCH 44/44] Readme fix --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 933539c..837adea 100644 --- a/README.md +++ b/README.md @@ -464,12 +464,14 @@ Quick example: ```objective-c - (void)cellDidLoad { - self.testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; - [self.contentView addSubview:self.testLabel]; + [super cellDidLoad]; + self.testLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 200, 44)]; + [self.contentView addSubview:self.testLabel]; } - (void)cellWillAppear { + [super cellWillAppear]; self.testLabel.text = self.item.someVariable; } ```