51 Commits

Author SHA1 Message Date
pastorin 00e512a37b Merge branch 'master' into addSections 2015-04-21 09:41:51 -03:00
pastorin f4129a367b Example - Add dynamic sections with multiple rows 2015-04-21 09:38:03 -03:00
Martin Barreto e14ed978c0 Merge pull request #317 from xmartlabs/deprecated
Fix NSHourCalendarUnit and NSMinuteCalendarUnit deprecated
2015-04-20 16:14:34 -03:00
Martin Barreto fb653663e8 Merge pull request #320 from xmartlabs/accessoryTypeIssue
Fix accessoryType limitations (issue #312)
2015-04-17 23:05:17 -03:00
Martin Barreto c5b88338cb Update XLFormButtonCell.m 2015-04-17 23:02:56 -03:00
Martin Barreto 8bd5656c67 delete podfile.lock 2015-04-17 21:23:21 -03:00
mats-claassen f6f51ea555 Merge pull request #319 from xmartlabs/duplicateSymbol
fix duplicate symbols (issue #311)
2015-04-17 16:13:12 -03:00
mats-claassen c17c6ff8dd Merge pull request #321 from xmartlabs/predicate_examples
Added more predicate examples and corrected minor things in readme.
2015-04-17 16:02:53 -03:00
Mathias Claassen 2782937274 Added more predicate examples and corrected minor things in readme. 2015-04-17 15:51:29 -03:00
pastorin 581fdbf561 Fix accessoryType limitations (issue #312) 2015-04-17 14:46:03 -03:00
pastorin 588a0b8734 fix duplicate symbols (issue #311) 2015-04-17 11:43:15 -03:00
pastorin e2118cba30 Fix NSHourCalendarUnit and NSMinuteCalendarUnit deprecated 2015-04-17 10:07:03 -03:00
Martin Barreto b817d1270e Merge branch 'predicate_rowDescriptor' 2015-04-17 04:41:17 -03:00
Martin Barreto 289603f952 merge 2015-04-17 04:40:10 -03:00
Martin Barreto eb4b1d67ca merge 2015-04-17 04:28:01 -03:00
Martin Barreto 5629922247 merge 2015-04-17 04:04:59 -03:00
Martin Barreto d5da7f807a comment out unused variables 2015-04-17 03:43:51 -03:00
Martin Barreto 802fb9a7c4 Merge branch 'predicate_rowDescriptor' of github.com:xmartlabs/XLForm into predicate_rowDescriptor 2015-04-17 03:39:30 -03:00
Martin Barreto 5bb7a4d82d fix unit test, make UITableView loads its cells on iOS 8.3 2015-04-17 03:39:03 -03:00
Martin Barreto 68d5d367d5 Merge pull request #315 from santiagofm/master
fixed formRowDescriptorValueHasChanged: not being called when datepicker...
2015-04-16 16:32:07 -03:00
Santiago Fernandez 6af0912cf7 fixed formRowDescriptorValueHasChanged: not being called when datepicker value changed 2015-04-16 16:28:24 -03:00
Mathias Claassen b6da136929 Merge branch 'predicate_rowDescriptor' of github.com:xmartlabs/XLForm into predicate_rowDescriptor 2015-04-16 16:25:45 -03:00
Mathias Claassen c3683c7ad7 added new predicate example for blog 2015-04-16 16:24:49 -03:00
Martin Barreto 9bc2f91d6b Merge pull request #314 from xmartlabs/addCountDownTimerType
Add count down timer type
2015-04-16 14:14:01 -03:00
pastorin 8ff180f6f4 minor change 2015-04-16 13:20:34 -03:00
pastorin 054f1803f0 add DateValueTransformer 2015-04-16 13:13:34 -03:00
Martin Barreto 27f0f78938 rename test file. 2015-04-16 13:05:49 -03:00
Martin Barreto b738d826f9 add observers at initialization time. 2015-04-16 02:15:14 -03:00
Martin Barreto 2ac23999fb Merge branch 'predicate_rowDescriptor' of github.com:xmartlabs/XLForm into predicate_rowDescriptor 2015-04-15 19:36:02 -03:00
Martin Barreto e8edb426c2 minor 2015-04-15 19:35:35 -03:00
Mathias Claassen 57fe1a64e2 bad_access bug removed 2015-04-15 15:46:06 -03:00
pastorin a8094d48b8 * Added XLFormRowDescriptorTypeCountDownTimerInline and XLFormRowDescriptorTypeCountDownTimer row type with an example.
* Deleted `dateFormatter` property and added support to use the `NSValueTransformer` to convert the selected object to a NSString in the XLFormDateCell class.
2015-04-15 15:23:54 -03:00
Mathias Claassen 730ec7ba58 tests 2015-04-15 13:41:43 -03:00
Martin Barreto 04b7ee6035 merge 2015-04-15 02:31:50 -03:00
Martin Barreto f0b7080a80 polish code. 2015-04-15 02:21:14 -03:00
Mathias Claassen ca201ba888 clean up code 2015-04-14 16:22:13 -03:00
Mathias Claassen 28e74bd134 doc 2015-04-14 11:23:58 -03:00
Martin Barreto 8b552c9632 minor 2015-04-14 02:28:40 -03:00
Martin Barreto bf9f11d307 Merge branch 'predicate_rowDescriptor' of github.com:xmartlabs/XLForm into predicate_rowDescriptor 2015-04-14 00:42:48 -03:00
Martin Barreto 05bd37f55a update icons. 2015-04-14 00:42:19 -03:00
Mathias Claassen 75558762bc Merge branch 'predicate_rowDescriptor' of github.com:xmartlabs/XLForm into predicate_rowDescriptor
Conflicts:
	XLForm/XL/Descriptors/XLFormDescriptor.m
	XLForm/XL/Descriptors/XLFormRowDescriptor.m
	XLForm/XL/Descriptors/XLFormSectionDescriptor.m
2015-04-13 15:44:21 -03:00
Mathias Claassen d84f09bf45 added test for disabled and hidden predicate property 2015-04-13 10:11:39 -03:00
Martin Barreto 6a275dbb56 Clean up code. Change interfaces to expose less methods. 2015-04-13 00:35:45 -03:00
Martin Barreto 998a4bc382 Merge branch 'master' into predicate_rowDescriptor 2015-04-12 20:53:00 -03:00
Martin Barreto 9143d6bd90 Merge branch 'master' of github.com:xmartlabs/XLForm 2015-04-12 20:33:06 -03:00
Martin Barreto 74be7af750 clean up code. 2015-04-12 20:32:41 -03:00
Mathias Claassen d43ff5c93d Hide / show predicates 2015-04-09 17:22:39 -03:00
Mathias Claassen d2a323feca hidden & disabled predicate added 2015-04-08 15:09:33 -03:00
Mathias Claassen da40cfaf5d predicates for disabling rows + example 2015-04-06 15:44:48 -03:00
Martin Barreto 176c7bebbe Merge pull request #297 from colmdoyle/master
Update Podfile of examples
2015-04-01 13:28:23 -03:00
Colm Doyle 94edd0015e Update Podfile of examples 2015-04-01 14:20:03 +01:00
68 changed files with 2316 additions and 337 deletions
+1
View File
@@ -21,3 +21,4 @@ DerivedData
Pods
Tests/Pods
Tests/Podfile.lock
Examples/Objective-C/Podfile.lock
@@ -26,16 +26,22 @@
#import "XLForm.h"
#import "AccessoryViewFormViewController.h"
//This macro defines if we use predicates to hide rows or do it manually the old way.
//Just comment out if you want it to run without predicates.
#define USE_PREDICATES_FOR_HIDING
@interface AccessoryViewFormViewController ()
@end
@implementation AccessoryViewFormViewController
{
#ifndef USE_PREDICATES_FOR_HIDING
XLFormRowDescriptor * _rowShowAccessoryView;
XLFormRowDescriptor * _rowStopDisableRow;
XLFormRowDescriptor * _rowStopInlineRow;
XLFormRowDescriptor * _rowSkipCanNotBecomeFirstResponderRow;
#endif
}
@@ -54,6 +60,8 @@ NSString * kAccessoryViewCheck = @"check";
NSString * kAccessoryViewNotes = @"notes";
-(id)init
{
self = [super init];
@@ -69,7 +77,7 @@ NSString * kAccessoryViewNotes = @"notes";
formDescriptor.rowNavigationOptions = XLFormRowNavigationOptionEnabled;
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;
XLFormRowDescriptor * switchRow;
// Configuration section
section = [XLFormSectionDescriptor formSectionWithTitle:@"Row Navigation Settings"];
@@ -77,29 +85,51 @@ NSString * kAccessoryViewNotes = @"notes";
[formDescriptor addFormSection:section];
// RowNavigationEnabled
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationEnabled rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Row Navigation Enabled?"];
row.value = @YES;
[section addFormRow:row];
switchRow = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationEnabled rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Row Navigation Enabled?"];
switchRow.value = @YES;
[section addFormRow:switchRow];
// RowNavigationShowAccessoryView
_rowShowAccessoryView = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationShowAccessoryView rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Show input accessory view?"];
_rowShowAccessoryView.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionEnabled) == XLFormRowNavigationOptionEnabled);
[section addFormRow:_rowShowAccessoryView];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationShowAccessoryView rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Show input accessory row?"];
row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionEnabled) == XLFormRowNavigationOptionEnabled);
[section addFormRow:row];
#ifdef USE_PREDICATES_FOR_HIDING
row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
#else
_rowShowAccessoryView = row;
#endif
// RowNavigationStopDisableRow
_rowStopDisableRow = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopDisableRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach disabled row?"];
_rowStopDisableRow.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopDisableRow) == XLFormRowNavigationOptionStopDisableRow);
[section addFormRow:_rowStopDisableRow];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopDisableRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach disabled row?"];
row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopDisableRow) == XLFormRowNavigationOptionStopDisableRow);
[section addFormRow:row];
#ifdef USE_PREDICATES_FOR_HIDING
row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
#else
_rowStopDisableRow = row;
#endif
// RowNavigationStopInlineRow
_rowStopInlineRow = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopInlineRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach inline row?"];
_rowStopInlineRow.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopInlineRow) == XLFormRowNavigationOptionStopInlineRow);
[section addFormRow:_rowStopInlineRow];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopInlineRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach inline row?"];
row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopInlineRow) == XLFormRowNavigationOptionStopInlineRow);
[section addFormRow:row];
#ifdef USE_PREDICATES_FOR_HIDING
row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
#else
_rowStopInlineRow = row;
#endif
// RowNavigationSkipCanNotBecomeFirstResponderRow
_rowSkipCanNotBecomeFirstResponderRow = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Skip Can Not Become First Responder Row?"];
_rowSkipCanNotBecomeFirstResponderRow.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow) == XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow);
[section addFormRow:_rowSkipCanNotBecomeFirstResponderRow];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Skip Can Not Become First Responder Row?"];
row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow) == XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow);
[section addFormRow:row];
#ifdef USE_PREDICATES_FOR_HIDING
row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
#else
_rowSkipCanNotBecomeFirstResponderRow = row;
#endif
// Basic Information - Section
section = [XLFormSectionDescriptor formSectionWithTitle:@"TextField Types"];
@@ -119,7 +149,7 @@ NSString * kAccessoryViewNotes = @"notes";
// Twitter
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewTwitter rowType:XLFormRowDescriptorTypeTwitter title:@"Twitter"];
row.disabled = YES;
row.disabled = @YES;
row.value = @"@no_editable";
[section addFormRow:row];
@@ -158,6 +188,7 @@ NSString * kAccessoryViewNotes = @"notes";
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)rowDescriptor oldValue:(id)oldValue newValue:(id)newValue
{
[super formRowDescriptorValueHasChanged:rowDescriptor oldValue:oldValue newValue:newValue];
#ifndef USE_PREDICATES_FOR_HIDING
NSString * kRowNavigationEnabled = @"kRowNavigationEnabled";
if ([rowDescriptor.tag isEqualToString:kRowNavigationEnabled]){
if ([[rowDescriptor.value valueData] isEqual:@NO]){
@@ -180,7 +211,9 @@ NSString * kAccessoryViewNotes = @"notes";
}
}
else if ([rowDescriptor.tag isEqualToString:kAccessoryViewRowNavigationStopDisableRow]){
else
#endif
if ([rowDescriptor.tag isEqualToString:kAccessoryViewRowNavigationStopDisableRow]){
if ([[rowDescriptor.value valueData] isEqual:@(YES)]){
self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptionStopDisableRow;
}
@@ -0,0 +1,35 @@
//
// DateAndTimeValueTransformer.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 <Foundation/Foundation.h>
@interface DateValueTrasformer : NSValueTransformer
@end
@interface DateTimeValueTrasformer : NSValueTransformer
@end
@interface DateAndTimeValueTrasformer : NSValueTransformer
@end
@@ -0,0 +1,89 @@
//
// DateAndTimeValueTransformer.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "DateAndTimeValueTrasformer.h"
@implementation DateValueTrasformer
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return NO;
}
- (id)transformedValue:(id)value
{
if (!value) return nil;
if ([value isKindOfClass:[NSDate class]]){
NSDate * date = (NSDate *)value;
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterFullStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
return [dateFormatter stringFromDate:date];
}
return nil;
}
@end
@implementation DateTimeValueTrasformer
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return NO;
}
- (id)transformedValue:(id)value
{
if (!value) return nil;
if ([value isKindOfClass:[NSDate class]]){
NSDate * date = (NSDate *)value;
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
return [dateFormatter stringFromDate:date];
}
return nil;
}
@end
@implementation DateAndTimeValueTrasformer
@end
@@ -26,13 +26,16 @@
NSString *const kDateInline = @"dateInline";
NSString *const kTimeInline = @"timeInline";
NSString *const kDateTimeInline = @"dateTimeInline";
NSString *const kCountDownTimerInline = @"countDownTimerInline";
NSString *const kDatePicker = @"datePicker";
NSString *const kDate = @"date";
NSString *const kTime = @"time";
NSString *const kDateTime = @"dateTime";
NSString *const kCountDownTimer = @"countDownTimer";
#import "DatesFormViewController.h"
@interface DatesFormViewController() <XLFormDescriptorDelegate>
@end
@implementation DatesFormViewController
@@ -43,9 +46,10 @@ NSString *const kDateTime = @"dateTime";
if (self){
XLFormDescriptor * form;
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;
form = [XLFormDescriptor formDescriptorWithTitle:@"Dates"];
form = [XLFormDescriptor formDescriptorWithTitle:@"Date & Time"];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Inline Dates"];
[form addFormSection:section];
@@ -55,16 +59,21 @@ NSString *const kDateTime = @"dateTime";
row.value = [NSDate new];
[section addFormRow:row];
// DateTime
// Time
row = [XLFormRowDescriptor formRowDescriptorWithTag:kTimeInline rowType:XLFormRowDescriptorTypeTimeInline title:@"Time"];
row.value = [NSDate new];
[section addFormRow:row];
// Time
// DateTime
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateTimeInline rowType:XLFormRowDescriptorTypeDateTimeInline title:@"Date Time"];
row.value = [NSDate new];
[section addFormRow:row];
// CountDownTimer
row = [XLFormRowDescriptor formRowDescriptorWithTag:kCountDownTimerInline rowType:XLFormRowDescriptorTypeCountDownTimerInline title:@"Countdown Timer"];
row.value = [NSDate new];
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Dates"];
[form addFormSection:section];
@@ -76,28 +85,43 @@ NSString *const kDateTime = @"dateTime";
[row.cellConfigAtConfigure setObject:[NSDate dateWithTimeIntervalSinceNow:(60*60*24*3)] forKey:@"maximumDate"];
[section addFormRow:row];
// DateTime
// Time
row = [XLFormRowDescriptor formRowDescriptorWithTag:kTime rowType:XLFormRowDescriptorTypeTime title:@"Time"];
[row.cellConfigAtConfigure setObject:@(10) forKey:@"minuteInterval"];
row.value = [NSDate new];
[section addFormRow:row];
// Time
// DateTime
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateTime rowType:XLFormRowDescriptorTypeDateTime title:@"Date Time"];
row.value = [NSDate new];
[section addFormRow:row];
// CountDownTimer
row = [XLFormRowDescriptor formRowDescriptorWithTag:kCountDownTimerInline rowType:XLFormRowDescriptorTypeCountDownTimer title:@"Countdown Timer"];
row.value = [NSDate new];
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Disabled Dates"];
section.footerTitle = @"DatesFormViewController.h";
//section.footerTitle = @"DatesFormViewController.h";
[form addFormSection:section];
// Date
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDate rowType:XLFormRowDescriptorTypeDate title:@"Date"];
row.disabled = YES;
row.disabled = @YES;
row.required = YES;
row.value = [NSDate new];
[section addFormRow:row];
// DatePicker
section = [XLFormSectionDescriptor formSectionWithTitle:@"DatePicker"];
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDatePicker rowType:XLFormRowDescriptorTypeDatePicker];
[row.cellConfigAtConfigure setObject:@(UIDatePickerModeDate) forKey:@"datePicker.datePickerMode"];
row.value = [NSDate new];
[section addFormRow:row];
self.form = form;
}
return self;
@@ -122,5 +146,19 @@ NSString *const kDateTime = @"dateTime";
[self.tableView reloadData];
}
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue
{
if([formRow.tag isEqualToString:kDatePicker])
{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"DatePicker"
message:@"Value Has changed!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message show];
}
}
@end
@@ -33,11 +33,14 @@
#import "UICustomizationFormViewController.h"
#import "CustomRowsViewController.h"
#import "AccessoryViewFormViewController.h"
#import "PredicateFormViewController.h"
NSString * const kTextFieldAndTextView = @"TextFieldAndTextView";
NSString * const kSelectors = @"Selectors";
NSString * const kOthes = @"Others";
NSString * const kDates = @"Dates";
NSString * const kPredicates = @"BasicPredicates";
NSString * const kBlogExample = @"BlogPredicates";
NSString * const kMultivalued = @"Multivalued";
NSString * const kMultivaluedOnlyReorder = @"MultivaluedOnlyReorder";
NSString * const kMultivaluedOnlyInsert = @"MultivaluedOnlyInsert";
@@ -106,7 +109,7 @@ NSString * const kValidations= @"Validations";
[section addFormRow:row];
// Dates
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDates rowType:XLFormRowDescriptorTypeButton title:@"Dates"];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDates rowType:XLFormRowDescriptorTypeButton title:@"Date & Time"];
row.action.viewControllerClass = [DatesFormViewController class];
[section addFormRow:row];
@@ -135,9 +138,7 @@ NSString * const kValidations= @"Validations";
row.action.viewControllerClass = [MultivaluedOnlyDeleteViewController class];
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"UI Customization"];
[form addFormSection:section];
@@ -168,6 +169,21 @@ NSString * const kValidations= @"Validations";
row.action.formSegueIdenfifier = @"ValidationExamplesFormViewControllerSegue";
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Using Predicates"];
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Very basic predicates"];
row.action.formSegueIdenfifier = @"BasicPredicateViewControllerSegue";
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Blog Example Hide predicates"];
row.action.formSegueIdenfifier = @"BlogExampleViewSegue";
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Another example"];
row.action.formSegueIdenfifier = @"PredicateFormViewControllerSegue";
[section addFormRow:row];
self.form = form;
}
@@ -68,7 +68,7 @@ NSString *const kNotes = @"notes";
// Twitter
row = [XLFormRowDescriptor formRowDescriptorWithTag:kTwitter rowType:XLFormRowDescriptorTypeTwitter title:@"Twitter"];
row.disabled = YES;
row.disabled = @YES;
row.value = @"@no_editable";
[section addFormRow:row];
@@ -71,6 +71,18 @@
row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3"];
section.multivaluedRowTemplate = [row copy];
[section addFormRow:row];
// Add Section Button
section = [XLFormSectionDescriptor formSection];
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"AddSectionButton" rowType:XLFormRowDescriptorTypeButton title:@"Add Section"];
row.action.formSelector = @selector(didTouchAddSectionButton:);
[row.cellConfigAtConfigure setObject:[UIColor clearColor] forKey:@"backgroundColor"];
[row.cellConfig setObject:[UIColor grayColor] forKey:@"textLabel.color"];
[row.cellConfig setObject:[UIFont fontWithName:@"Helvetica" size:17] forKey:@"textLabel.font"];
[section addFormRow:row];
return [super initWithForm:form];
}
@@ -90,6 +102,25 @@
}
-(void)didTouchAddSectionButton:(XLFormRowDescriptor *)sender
{
// Create a new section
XLFormSectionDescriptor * newSection = [XLFormSectionDescriptor formSectionWithTitle:[NSString stringWithFormat:@"Section created at %@", [NSDateFormatter localizedStringFromDate:[NSDate new] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]]];
newSection.multivaluedTag = [NSString stringWithFormat:@"multivaluedPushSelector_%@", @(self.form.formSections.count-1)];
// Add rows to the new section
XLFormRowDescriptor * newRow = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorPush title:@"Language"];
newRow.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3"];
[newSection addFormRow:newRow];
newRow = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorPush title:@"Level"];
newRow.selectorOptions = @[@"Option A", @"Option B", @"Option C"];
[newSection addFormRow:newRow];
// Add new section
[self.form addFormSection:newSection beforeSection:sender.sectionDescriptor];
[self deselectFormRow:sender];
}
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
@@ -116,6 +147,7 @@
}
}
@end
@@ -0,0 +1,31 @@
//
// BasicPredicateViewController.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "XLForm.h"
#import "XLFormViewController.h"
@interface BasicPredicateViewController : XLFormViewController
@end
@@ -0,0 +1,84 @@
//
// BasicPredicateViewController.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "BasicPredicateViewController.h"
NSString *const khiderow = @"tag1";
NSString *const khidesection = @"tag2";
NSString *const ktext = @"tag3";
@implementation BasicPredicateViewController
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self initializeForm];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self initializeForm];
}
return self;
}
- (void)initializeForm
{
XLFormDescriptor * form;
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;
form = [XLFormDescriptor formDescriptorWithTitle:@"Basic Predicates"];
section = [XLFormSectionDescriptor formSectionWithTitle:@"A Section"];
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:khiderow rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Show next row"];
row.value = @0;
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:khidesection rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Show B Section"];
row.hidden = [NSString stringWithFormat:@"$%@==0", khiderow];
row.value = @0;
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"B Section"];
section.footerTitle = @"BasicPredicateViewController";
section.hidden = [NSString stringWithFormat:@"$%@==0", khidesection];
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:ktext rowType:XLFormRowDescriptorTypeText title:@""];
[row.cellConfigAtConfigure setObject:@"Gonna disappear soon!!" forKey:@"textField.placeholder"];
[section addFormRow:row];
self.form = form;
}
@end
@@ -0,0 +1,31 @@
//
// BlogExampleViewController.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "XLForm.h"
#import "XLFormViewController.h"
@interface BlogExampleViewController : XLFormViewController
@end
@@ -0,0 +1,109 @@
//
// BlogExampleViewController.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "BlogExampleViewController.h"
NSString *const kHobbies = @"hobbies";
NSString *const kSport = @"sport";
NSString *const kFilm = @"films1";
NSString *const kFilm2 = @"films2";
NSString *const kMusic = @"music";
@interface BlogExampleViewController ()
@end
@implementation BlogExampleViewController
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self initializeForm];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self initializeForm];
}
return self;
}
- (void)initializeForm
{
XLFormDescriptor * form;
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;
form = [XLFormDescriptor formDescriptorWithTitle:@"Blog Example: Hobbies"];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Hobbies"];
[form addFormSection:section];
XLFormRowDescriptor* hobbyRow = [XLFormRowDescriptor formRowDescriptorWithTag:kHobbies
rowType:XLFormRowDescriptorTypeMultipleSelector
title:@"Select Hobbies"];
hobbyRow.selectorOptions = @[@"Sport", @"Music", @"Films"];
hobbyRow.value = @[];
[section addFormRow:hobbyRow];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Some more questions"];
section.hidden = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"$%@.value.@count = 0", hobbyRow]];
section.footerTitle = @"BlogExampleViewController.m";
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSport
rowType:XLFormRowDescriptorTypeTextView
title:@"Your favourite sportsman?"];
row.hidden = [NSString stringWithFormat:@"NOT $%@.value contains 'Sport'", hobbyRow];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kFilm
rowType:XLFormRowDescriptorTypeTextView
title:@"Your favourite film?"];
row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Films'", hobbyRow];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kFilm2
rowType:XLFormRowDescriptorTypeTextView
title:@"Your favourite actor?"];
row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Films'", hobbyRow];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kMusic
rowType:XLFormRowDescriptorTypeTextView
title:@"Your favourite singer?"];
row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Music'", hobbyRow];
[section addFormRow:row];
self.form = form;
}
@end
@@ -0,0 +1,31 @@
//
// PredicateFormViewController.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "XLForm.h"
#import "XLFormViewController.h"
@interface PredicateFormViewController : XLFormViewController
@end
@@ -0,0 +1,113 @@
//
// PredicateFormViewController.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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.
NSString *const kPred = @"pred";
NSString *const kPredDep = @"preddep";
NSString *const kPredDep2 = @"preddep2";
#import "PredicateFormViewController.h"
@implementation PredicateFormViewController
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
[self initializeForm];
}
return self;
}
- (instancetype)init
{
self = [super init];
if (self) {
[self initializeForm];
}
return self;
}
- (void)initializeForm
{
XLFormDescriptor * form;
XLFormSectionDescriptor * section;
XLFormRowDescriptor * row;
XLFormRowDescriptor * pred, *pred3, *pred4;
form = [XLFormDescriptor formDescriptorWithTitle:@"Predicates example"];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Independent rows"];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredDep rowType:XLFormRowDescriptorTypeAccount title:@"Text"];
[row.cellConfigAtConfigure setObject:@"Type disable" forKey:@"textField.placeholder"];
pred = row;
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredDep2 rowType:XLFormRowDescriptorTypeInteger title:@"Integer"];
row.hidden = [NSString stringWithFormat:@"$switch==0"];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"switch" rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Boolean"];
row.value = @1;
pred3 = row;
[section addFormRow:row];
[form addFormSection:section];
section = [XLFormSectionDescriptor formSectionWithTitle:@"Dependent section"];
section.footerTitle = @"Type disable in the textfield, a number between 18 and 60 in the integer field or use the switch to disable the last row. By doing all three the last section will hide.\nThe integer field hides when the boolean switch is set to 0.";
[form addFormSection:section];
// Predicate Disabling
row = [XLFormRowDescriptor formRowDescriptorWithTag:kPred rowType:XLFormRowDescriptorTypeDateInline title:@"Disabled"];
row.value = [NSDate new];
[section addFormRow:row];
row.disabled = [NSString stringWithFormat:@"$%@ contains[c] 'disable' OR ($%@.value between {18, 60}) OR ($%@.value == 0)", pred, kPredDep2, pred3];
//[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"($%@.value contains[c] %%@) OR ($%@.value between {18, 60}) OR ($%@.value == 0)", pred, pred2, pred3], @"disable"] ];
pred4 = row;
section.hidden = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"($%@.value contains[c] 'disable') AND ($%@.value between {18, 60}) AND ($%@.value == 0)", pred, kPredDep2, pred3]];
section = [XLFormSectionDescriptor formSectionWithTitle:@"More predicates..."];
section.footerTitle = @"This row hides when the row of the previous section is disabled and the textfield in the first section contains \"out\"\n\nPredicateFormViewController.m";
[form addFormSection:section];
row = [XLFormRowDescriptor formRowDescriptorWithTag:@"thirds" rowType:XLFormRowDescriptorTypeAccount title:@"Account"];
[section addFormRow:row];
row.hidden = [NSString stringWithFormat:@"$%@.isDisabled == 1 AND $%@.value contains[c] 'Out'", pred4, pred];
self.form = form;
}
@end
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

@@ -24,8 +24,10 @@
// THE SOFTWARE.
#import "XLForm.h"
#import "DateAndTimeValueTrasformer.h"
#import "NativeEventFormViewController.h"
@implementation NativeEventNavigationViewController
-(id)init
@@ -188,7 +190,7 @@
if ([[rowDescriptor.value valueData] isEqualToNumber:@(0)] == NO && [[oldValue valueData] isEqualToNumber:@(0)]){
XLFormRowDescriptor * newRow = [rowDescriptor copy];
[newRow setTag:@"secondAlert"];
newRow.tag = @"secondAlert";
newRow.title = @"Second Alert";
[self.form addFormRow:newRow afterRow:rowDescriptor];
}
@@ -197,23 +199,22 @@
}
}
else if ([rowDescriptor.tag isEqualToString:@"all-day"]){
XLFormRowDescriptor * startDateDescriptor = [self.form formRowWithTag:@"starts"];
XLFormRowDescriptor * endDateDescriptor = [self.form formRowWithTag:@"ends"];
XLFormDateCell * dateStartCell = (XLFormDateCell *)[[self.form formRowWithTag:@"starts"] cellForFormController:self];
XLFormDateCell * dateEndCell = (XLFormDateCell *)[[self.form formRowWithTag:@"ends"] cellForFormController:self];
NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
if ([[rowDescriptor.value valueData] boolValue] == YES){
[dateFormatter setDateStyle:NSDateFormatterFullStyle];
[dateFormatter setTimeStyle:NSDateFormatterNoStyle];
startDateDescriptor.valueTransformer = [DateValueTrasformer class];
endDateDescriptor.valueTransformer = [DateValueTrasformer class];
[dateStartCell setFormDatePickerMode:XLFormDateDatePickerModeDate];
[dateEndCell setFormDatePickerMode:XLFormDateDatePickerModeDate];
}
else{
[dateFormatter setDateStyle:NSDateFormatterMediumStyle];
[dateFormatter setTimeStyle:NSDateFormatterShortStyle];
startDateDescriptor.valueTransformer = [DateTimeValueTrasformer class];
endDateDescriptor.valueTransformer = [DateTimeValueTrasformer class];
[dateStartCell setFormDatePickerMode:XLFormDateDatePickerModeDateTime];
[dateEndCell setFormDatePickerMode:XLFormDateDatePickerModeDateTime];
}
dateStartCell.dateFormatter = dateFormatter;
dateEndCell.dateFormatter = dateFormatter;
[dateStartCell update];
[dateEndCell update];
}
@@ -325,7 +325,7 @@ NSString *const kSelectorWithStoryboardId = @"selectorWithStoryboardId";
// Disabled Selector Push
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorPushDisabled rowType:XLFormRowDescriptorTypeSelectorPush title:@"Push"];
row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"];
row.disabled = YES;
row.disabled = @YES;
[section addFormRow:row];
@@ -334,7 +334,7 @@ NSString *const kSelectorWithStoryboardId = @"selectorWithStoryboardId";
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorActionSheetDisabled rowType:XLFormRowDescriptorTypeSelectorActionSheet title:@"Sheet"];
row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"];
row.disabled = YES;
row.disabled = @YES;
[section addFormRow:row];
// --------- Disabled Selector Left Right
@@ -342,7 +342,7 @@ NSString *const kSelectorWithStoryboardId = @"selectorWithStoryboardId";
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorLeftRightDisabled rowType:XLFormRowDescriptorTypeSelectorLeftRight title:@"Left Right"];
row.leftRightSelectorLeftOptionSelected = [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"];
row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Right Option 4"];
row.disabled = YES;
row.disabled = @YES;
[section addFormRow:row];
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6250" systemVersion="14A389" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="p4n-1v-pzo">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7531" systemVersion="14D131" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="p4n-1v-pzo">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6244"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
@@ -111,12 +111,34 @@
<segue destination="G68-Ra-1fb" kind="push" identifier="SelectorsFormViewControllerSegue" id="vhA-cV-A02"/>
<segue destination="K9D-4c-9eZ" kind="modal" identifier="NativeEventNavigationViewControllerSegue" id="Iie-Js-Izx"/>
<segue destination="Kiw-nF-jv7" kind="push" identifier="ValidationExamplesFormViewControllerSegue" id="VKe-Ir-Fiu"/>
<segue destination="OG6-Tc-1SC" kind="push" identifier="PredicateFormViewControllerSegue" id="Wwg-e9-gLq"/>
<segue destination="pO0-sS-Tes" kind="push" identifier="BlogExampleViewSegue" id="a28-Gm-Iku"/>
<segue destination="JL7-uU-kWK" kind="push" identifier="BasicPredicateViewControllerSegue" id="SGg-Ve-bng"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1V5-DZ-WfF" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="527" y="56"/>
</scene>
<!--Blog Example View Controller-->
<scene sceneID="Vn0-9y-5bc">
<objects>
<viewController id="pO0-sS-Tes" customClass="BlogExampleViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="gjZ-Jv-Awa"/>
<viewControllerLayoutGuide type="bottom" id="scM-da-Sg0"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="hrV-fb-58s">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="RJB-cz-SnF"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Fvo-wr-5Ca" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="167" y="1151"/>
</scene>
<!--Validation Examples-->
<scene sceneID="z2I-Nk-y9W">
<objects>
@@ -151,7 +173,26 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="VFT-Og-STO" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="527" y="789"/>
<point key="canvasLocation" x="566" y="938"/>
</scene>
<!--Predicate Form View Controller-->
<scene sceneID="a9p-C8-g8y">
<objects>
<viewController id="OG6-Tc-1SC" customClass="PredicateFormViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="2YH-dK-JXQ"/>
<viewControllerLayoutGuide type="bottom" id="Lsg-dH-McH"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="6EZ-O7-FjX">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="Lsd-xH-7IN"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="rZL-10-YZn" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="956" y="924"/>
</scene>
<!--Selectors Form View Controller-->
<scene sceneID="KYK-TX-8rm">
@@ -212,6 +253,25 @@
</objects>
<point key="canvasLocation" x="588" y="-635"/>
</scene>
<!--Basic Predicate View Controller-->
<scene sceneID="pD4-sm-x3a">
<objects>
<viewController id="JL7-uU-kWK" customClass="BasicPredicateViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="OQP-pW-kNp"/>
<viewControllerLayoutGuide type="bottom" id="2b4-gN-85p"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="NZg-t1-g19">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="1lh-jZ-lIV"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Tlw-q2-pcu" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="-159" y="1151"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
-47
View File
@@ -1,47 +0,0 @@
PODS:
- AFNetworking (2.4.1):
- AFNetworking/NSURLConnection (= 2.4.1)
- AFNetworking/NSURLSession (= 2.4.1)
- AFNetworking/Reachability (= 2.4.1)
- AFNetworking/Security (= 2.4.1)
- AFNetworking/Serialization (= 2.4.1)
- AFNetworking/UIKit (= 2.4.1)
- AFNetworking/NSURLConnection (2.4.1):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/NSURLSession (2.4.1):
- AFNetworking/Reachability
- AFNetworking/Security
- AFNetworking/Serialization
- AFNetworking/Reachability (2.4.1)
- AFNetworking/Security (2.4.1)
- AFNetworking/Serialization (2.4.1)
- AFNetworking/UIKit (2.4.1):
- AFNetworking/NSURLConnection
- AFNetworking/NSURLSession
- AXRatingView (1.0.3)
- JVFloatLabeledTextField (1.0.2)
- XLDataLoader (1.1.0):
- AFNetworking (~> 2.0)
- XLForm (2.1.0)
DEPENDENCIES:
- AFNetworking (~> 2.0)
- AXRatingView (= 1.0.3)
- JVFloatLabeledTextField (= 1.0.2)
- XLDataLoader (~> 1.1)
- XLForm (from `../../`)
EXTERNAL SOURCES:
XLForm:
:path: ../../
SPEC CHECKSUMS:
AFNetworking: 0aabc6fae66d6e5d039eeb21c315843c7aae51ab
AXRatingView: 4f6d6c96f6d0efc1deaa6cf493dbb1ffcfa79e55
JVFloatLabeledTextField: c1ad6b4b5bd77115cfe6c71ba4c023866df5c4cf
XLDataLoader: bd783ebe782932a6390ffc7619fcd884c8600944
XLForm: c87bc94f769f52ce32793282d72d2fb15d0d5638
COCOAPODS: 0.35.0
@@ -49,6 +49,10 @@
3C3B01E21AB7499A0027CD45 /* XLRatingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01E01AB7499A0027CD45 /* XLRatingView.m */; };
3C3B01F01AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01EF1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m */; };
3CDAFC7A1AB0AFA4000F75B6 /* CustomRowsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CDAFC791AB0AFA4000F75B6 /* CustomRowsViewController.m */; };
66B6266E1AE0055100007886 /* DateAndTimeValueTrasformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */; };
BF9DB1D51AE0436600B985E7 /* BlogExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */; };
BF9DB1D61AE0436600B985E7 /* PredicateFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */; };
BFE91AFB1AE159B200DE5231 /* BasicPredicateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */; };
D51B8B2C19126664008C0478 /* XLFormCustomCell.m in Sources */ = {isa = PBXBuildFile; fileRef = D51B8B2B19126664008C0478 /* XLFormCustomCell.m */; };
/* End PBXBuildFile section */
@@ -125,8 +129,16 @@
3C3B01EF1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FloatLabeledTextFieldCell.m; path = Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.m; sourceTree = "<group>"; };
3CDAFC781AB0AFA4000F75B6 /* CustomRowsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomRowsViewController.h; path = Examples/CustomRows/CustomRowsViewController.h; sourceTree = "<group>"; };
3CDAFC791AB0AFA4000F75B6 /* CustomRowsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CustomRowsViewController.m; path = Examples/CustomRows/CustomRowsViewController.m; sourceTree = "<group>"; };
66B6266C1AE0055100007886 /* DateAndTimeValueTrasformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DateAndTimeValueTrasformer.h; path = Examples/Dates/DateAndTimeValueTrasformer.h; sourceTree = "<group>"; };
66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DateAndTimeValueTrasformer.m; path = Examples/Dates/DateAndTimeValueTrasformer.m; sourceTree = "<group>"; };
7B0D2D6A86E2A41ED22E8A35 /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
976A33EE62A018A7257B4878 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
BF9DB1D11AE0436600B985E7 /* BlogExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlogExampleViewController.h; path = Examples/PredicateExamples/BlogExampleViewController.h; sourceTree = SOURCE_ROOT; };
BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BlogExampleViewController.m; path = Examples/PredicateExamples/BlogExampleViewController.m; sourceTree = SOURCE_ROOT; };
BF9DB1D31AE0436600B985E7 /* PredicateFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PredicateFormViewController.h; path = Examples/PredicateExamples/PredicateFormViewController.h; sourceTree = SOURCE_ROOT; };
BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PredicateFormViewController.m; path = Examples/PredicateExamples/PredicateFormViewController.m; sourceTree = SOURCE_ROOT; };
BFE91AF91AE159B200DE5231 /* BasicPredicateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BasicPredicateViewController.h; path = Examples/PredicateExamples/BasicPredicateViewController.h; sourceTree = SOURCE_ROOT; };
BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BasicPredicateViewController.m; path = Examples/PredicateExamples/BasicPredicateViewController.m; sourceTree = SOURCE_ROOT; };
D51B8B2A19126664008C0478 /* XLFormCustomCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLFormCustomCell.h; path = Examples/Others/CustomCells/XLFormCustomCell.h; sourceTree = "<group>"; };
D51B8B2B19126664008C0478 /* XLFormCustomCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormCustomCell.m; path = Examples/Others/CustomCells/XLFormCustomCell.m; sourceTree = "<group>"; };
F6DF43B7BBF44F72A4493E8E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -231,6 +243,8 @@
2843EB5318D4F77F00F13E2B /* Dates */ = {
isa = PBXGroup;
children = (
66B6266C1AE0055100007886 /* DateAndTimeValueTrasformer.h */,
66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */,
2843EB5418D4F7B700F13E2B /* DatesFormViewController.h */,
2843EB5518D4F7B700F13E2B /* DatesFormViewController.m */,
);
@@ -322,6 +336,7 @@
2843EB4F18D4CFA100F13E2B /* Others */,
2843EB4818D496CB00F13E2B /* Selectors */,
2850C60A18D0F706002B7D0A /* AppDelegate.h */,
BFD5D6F41AD2FFC1006F04FA /* PredicateExamples */,
282C5EEF18D33C1800A5D47C /* Inputs */,
2843EB4518D4915800F13E2B /* ExamplesFormViewController.h */,
2843EB4618D4915800F13E2B /* ExamplesFormViewController.m */,
@@ -473,6 +488,20 @@
name = CustomRows;
sourceTree = "<group>";
};
BFD5D6F41AD2FFC1006F04FA /* PredicateExamples */ = {
isa = PBXGroup;
children = (
BF9DB1D11AE0436600B985E7 /* BlogExampleViewController.h */,
BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */,
BF9DB1D31AE0436600B985E7 /* PredicateFormViewController.h */,
BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */,
BFE91AF91AE159B200DE5231 /* BasicPredicateViewController.h */,
BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */,
);
name = PredicateExamples;
path = Examples/PredicateDisabling;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -581,6 +610,7 @@
3CDAFC7A1AB0AFA4000F75B6 /* CustomRowsViewController.m in Sources */,
28A7663B1932EA1F00D69546 /* UserLocalDataLoader.m in Sources */,
282EB27C1AB5FF33004A736F /* AccessoryViewFormViewController.m in Sources */,
BF9DB1D51AE0436600B985E7 /* BlogExampleViewController.m in Sources */,
2850C60818D0F706002B7D0A /* main.m in Sources */,
D51B8B2C19126664008C0478 /* XLFormCustomCell.m in Sources */,
28A7664D1932EE0B00D69546 /* User.m in Sources */,
@@ -592,6 +622,7 @@
28468E9818EC686500DBB015 /* NativeEventFormViewController.m in Sources */,
3C3B01DA1AB7497D0027CD45 /* XLFormWeekDaysCell.m in Sources */,
28F89F2E1AA4EA5600E90218 /* ValidationExamplesFormViewController.m in Sources */,
66B6266E1AE0055100007886 /* DateAndTimeValueTrasformer.m in Sources */,
3C3B01D51AB741EF0027CD45 /* XLFormRatingCell.m in Sources */,
28A7665E1932F61100D69546 /* DynamicSelectorsFormViewController.m in Sources */,
281E5BE919538F4A006D93C5 /* CLLocationValueTrasformer.m in Sources */,
@@ -602,7 +633,9 @@
283B59B219532415000828CD /* MapViewController.m in Sources */,
2843EB4718D4915800F13E2B /* ExamplesFormViewController.m in Sources */,
28A766451932EC9C00D69546 /* CoreDataStore.m in Sources */,
BF9DB1D61AE0436600B985E7 /* PredicateFormViewController.m in Sources */,
28A7663C1932EA1F00D69546 /* UserRemoteDataLoader.m in Sources */,
BFE91AFB1AE159B200DE5231 /* BasicPredicateViewController.m in Sources */,
2843EB5218D4CFC700F13E2B /* OthersFormViewController.m in Sources */,
2843EB4B18D496F600F13E2B /* SelectorsFormViewController.m in Sources */,
28468EA418EF41D300DBB015 /* InputsFormViewController.m in Sources */,
@@ -1,15 +1,40 @@
{
"images" : [
{
"size" : "29x29",
"idiom" : "iphone",
"filename" : "xl_appicon_58.png",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"size" : "40x40",
"idiom" : "iphone",
"filename" : "xl_appicon_80.png",
"size" : "29x29",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x"
},
{
"size" : "57x57",
"idiom" : "iphone",
"filename" : "xl_appicon_57.png",
"scale" : "1x"
},
{
"size" : "57x57",
"idiom" : "iphone",
"filename" : "xl_appicon_114.png",
"scale" : "2x"
},
{
@@ -22,6 +47,117 @@
"idiom" : "iphone",
"size" : "60x60",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "50x50",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "50x50",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "72x72",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "72x72",
"scale" : "2x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "xl_appicon_76.png",
"scale" : "1x"
},
{
"size" : "76x76",
"idiom" : "ipad",
"filename" : "xl_appicon_152.png",
"scale" : "2x"
},
{
"idiom" : "car",
"size" : "120x120",
"scale" : "1x"
},
{
"size" : "24x24",
"idiom" : "watch",
"scale" : "2x",
"role" : "notificationCenter",
"subtype" : "38mm"
},
{
"size" : "27.5x27.5",
"idiom" : "watch",
"scale" : "2x",
"role" : "notificationCenter",
"subtype" : "42mm"
},
{
"size" : "29x29",
"idiom" : "watch",
"role" : "companionSettings",
"scale" : "2x"
},
{
"size" : "29x29",
"idiom" : "watch",
"role" : "companionSettings",
"scale" : "3x"
},
{
"size" : "40x40",
"idiom" : "watch",
"scale" : "2x",
"role" : "appLauncher",
"subtype" : "38mm"
},
{
"size" : "44x44",
"idiom" : "watch",
"scale" : "2x",
"role" : "longLook",
"subtype" : "42mm"
},
{
"size" : "86x86",
"idiom" : "watch",
"scale" : "2x",
"role" : "quickLook",
"subtype" : "38mm"
},
{
"size" : "98x98",
"idiom" : "watch",
"scale" : "2x",
"role" : "quickLook",
"subtype" : "42mm"
}
],
"info" : {
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 823 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

-14
View File
@@ -1,14 +0,0 @@
PODS:
- XLForm (2.1.0)
DEPENDENCIES:
- XLForm (from `../../`)
EXTERNAL SOURCES:
XLForm:
:path: ../../
SPEC CHECKSUMS:
XLForm: c87bc94f769f52ce32793282d72d2fb15d0d5638
COCOAPODS: 0.35.0
+106 -10
View File
@@ -28,8 +28,10 @@ What XLForm does
* Supports custom selectors. For further details of how to define your own selectors check [*Custom selectors*](#custom-selectors---selector-row-with-a-custom-selector-view-controller "Custom Selectors") section out.
* Provides several inline selectors such as date picker and picker inline selectors and brings a way to create custom inline selectors.
* Form data validation based on form definition.
* Ability to easily navigate among rows, fully customizable. * Ability to show inputAccessoryView if needed. By default a navigation input accessory view is shown.
* Ability to easily navigate among rows, fully customizable.
* Ability to show inputAccessoryView if needed. By default a navigation input accessory view is shown.
* Read only mode for a particular row or the entire form.
* Rows can be hidden or shown depending on other rows values. This can be done declaratively using `NSPredicates`. (see [*Make a row or section invisible depending on other rows values*](#make-a-row-or-section-invisible-depending-on-other-rows-values "Using Predicates"))
@@ -240,9 +242,9 @@ This is the protocol declaration:
```
####Date Rows
####Date & Time Rows
XLForms supports 3 types of dates: `Date`, `DateTime` and `Time` and it's able to present the `UIDatePicker` control in 2 different ways, inline and non-inline.
XLForms supports 3 types of dates: `Date`, `DateTime` , `Time` and `Countdown Timer` and it's able to present the `UIDatePicker` control in 2 different ways, inline and non-inline.
![Screenshot of native Calendar Event Example](Examples/Objective-C/Examples/Dates/XLForm-Dates.gif)
@@ -259,6 +261,10 @@ static NSString *const XLFormRowDescriptorTypeDateTimeInline = @"datetimeInline"
static NSString *const XLFormRowDescriptorTypeTimeInline = @"timeInline";
```
```objc
static NSString *const XLFormRowDescriptorTypeCountDownTimerInline = @"countDownTimerInline";
```
```objc
static NSString *const XLFormRowDescriptorTypeDate = @"date";
```
@@ -271,6 +277,10 @@ static NSString *const XLFormRowDescriptorTypeDateTime = @"datetime";
static NSString *const XLFormRowDescriptorTypeTime = @"time";
```
```objc
static NSString *const XLFormRowDescriptorTypeCountDownTimer = @"countDownTimer";
```
Here is an example of how to define these row types:
@@ -298,6 +308,11 @@ row.value = [NSDate new];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateTimeInline rowType:XLFormRowDescriptorTypeDateTimeInline title:@"Date Time"];
row.value = [NSDate new];
[section addFormRow:row];
// CountDownTimer
row = [XLFormRowDescriptor formRowDescriptorWithTag:kCountDownTimerInline rowType:XLFormRowDescriptorTypeCountDownTimerInline title:@"Countdown Timer"];
row.value = [NSDate new];
[section addFormRow:row];
```
@@ -571,16 +586,18 @@ You can find the details of these examples within the example repository folder,
Dynamic Forms - How to change the form dynamically at runtime
-------------------------------
Any change made on the `XLFormDescriptor` will be reflected on the `XLFormViewController` tableView. That means that we can add or remove sections or rows at any time and XLForm will animate the section or row accordingly.
Any change made on the `XLFormDescriptor` will be reflected on the `XLFormViewController` tableView. That means that when a section or a row is added or removed XLForm will animate the section or row accordingly.
We shouldn't have to deal with `NSIndexPaths` or add, remove `UITableViewCell` anymore. `NSIndexPath` of a specific `TableViewCell` changes along the time and this makes very hard to keep track of the `NSIndexPath` of each `UITableViewCell`.
Each XLForm `XLFormRowDescriptor` row has a `tag` property that is set up in its constructor. `XLFormDescriptor` has, among other helpers, an specific one to get a `XLFormRowDescriptor` from a `tag`.
It's much easier to manage `XLFormRowDescriptor`s using tags, the tag should be unique and it doesn't change on tableview additions modifications or deletions.
It's important keep in mind that all the `UITableView` form modifications have to be made using the descriptors and not making modifications directly on the `UITableView`.
It's important to keep in mind that all the `UITableView` form modifications have to be made using the descriptors and not making modifications directly on the `UITableView`.
Usually you may want to change the form when some value change or some row or section is added or removed. In order to keep posted about the form descriptor modifications your `XLFormViewController` subclass should override the `XLFormDescriptorDelegate` methods of 'XLFormViewController'.
Usually you may want to change the form when some value change or some row or section is added or removed. For this you can set the `disabled` and `hidden` properties of the rows or sections. For more details see [*Make a row or section invisible depending on other rows values*](#make-a-row-or-section-invisible-depending-on-other-rows-values "Using Predicates").
In order to stay in sync with the form descriptor modifications your `XLFormViewController` subclass should override the `XLFormDescriptorDelegate` methods of 'XLFormViewController'.
```objc
@protocol XLFormDescriptorDelegate <NSObject>
@@ -616,6 +633,60 @@ For instance if we want to show or hide a row depending on the value of another
}
```
Make a row or section invisible depending on other rows values
--------------------------------
###Summary
XLForm allows you to define dependencies between rows so that if the value of one row is changed, the behaviour of another one changes automatically. For example, you might have a form where you question the user if he/she has pets. If the answer is 'yes' you might want to ask how their names are.
So you can make a row invisible and visible again based on the values of other rows. The same happens with sections.
Take a look at the following example:
![Screenshot of hiding rows](Examples/Objective-C/Examples/PredicateExamples/XLFormPredicatesBasic.gif)
Of course, you could also do this manually by observing the value of some rows and deleting and adding rows accordingly, but that would be a lot of work which is already done.
###How it works
To make the appearance and disappearance of rows and sections automatic, there is a property in each descriptor:
```objc
@property id hidden;
```
This id object will normally be a NSPredicate or a NSNumber containing a BOOL. It can be set using any of them or eventually a NSString from which a NSPredicate will be created. In order for this to work the string has to be sintactically correct.
For example, you could set the following string to a row (`second`) to make it disappear when a previous row (`first`) contains the value "hide".
```objc
second.hidden = [NSString stringWithFormat:@"$%@ contains[c] 'hide'", first];
```
This will insert the tag of the `first` after the '$', you can do that manually as well, of course. When the predicate is evaluated every tag variable gets substituted by the corresponding row descriptor.
When the argument is a NSString, a '.value' will be appended to every tag unless the tag is followed by '.isHidden' or '.isDisabled'. This means that a row (or section) might depend on the `value` or the `hidden` or `disabled` properties of another row. When the property is set with a NSPredicate directly, its formatString will not be altered (so you have to append a '.value' after each variable if you want to refer to its value). Setting a NSString is the simplest way but some complex predicates might not work so for those you should directly set a NSPredicate.
You can also set this properties with a bool object which means the value of the property will not change unless manually set.
To get the evaluated boolean value the `isHidden` method should be called. It will not re-evaluate the predicate each time it gets called but just when the value (or hidden/disabled status) of the rows it depends on changes. When this happens and the return value changes, it will automagically reflect that change on the form so that no other method must be called.
Here is another example, this time a bit more complex:
![Screenshot of hiding rows](Examples/Objective-C/Examples/PredicateExamples/XLFormPredicates.gif)
Disabling rows (set to read-only mode)
--------------------------------
Rows can be disabled so that the user can not change them. By default disabled rows have a gray text color. To disable a row the only thing that has to be done is setting its disabled property:
```objc
@property id disabled;
```
This property expects a NSNumber containing a BOOL, a NSString or a NSPredicate. A bool will statically disable (or enable the row). The other two work just like the hidden property explained in the section above. This means a row can be disabled and enabled depending on the values of other rows. When a NSString is set, a NSPredicate will be generated taking the string as format string so that it has to be consistent for that purpose.
A difference to the hidden property is that checking the disabled status of a row does not automatically reflect that value on the form. Tharefore, the XLFormViewController's updateFormRow method should be called.
Validations
------------------------------------
@@ -657,7 +728,7 @@ To get all rows validation errors we can invoke the following `XLFormViewControl
Additional configuration of Rows
--------------------------------
`XLFormRowDescriptor` allow us to configure generic aspects of a `UITableViewCell`, for example: the `rowType`, the `label`, the `value` (default value), if the cell is `required` or `disabled`, and so on.
`XLFormRowDescriptor` allow us to configure generic aspects of a `UITableViewCell`, for example: the `rowType`, the `label`, the `value` (default value), if the cell is `required`, `hidden` or `disabled`, and so on.
You may want to set up another properties of the `UITableViewCell`. To set up another properties `XLForm` makes use of [Key-Value Coding](https://developer.apple.com/LIBRARY/IOS/documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html "Key-Value Coding") allowing the developer to set the cell properties by keyPath.
@@ -681,6 +752,7 @@ row = [XLFormRowDescriptor formRowDescriptorWithTag:@"title" rowType:XLFormRowDe
[section addFormRow:row];
```
FAQ
-------
@@ -764,9 +836,24 @@ For further details, please take a look at [UICustomizationFormViewController.m]
####How to disable the entire form (read only mode).
`disable` XLFormDescriptor property can be used to disable the entire form. In order to make the displayed cell to take effect we should reload the visible cells ( [self.tableView reloadData] ).
`disable` XLFormDescriptor property can be used to disable the entire form. In order to make the displayed cell to take effect we should reload the visible cells ( [self.tableView reloadData] ).
Any other row added after form `disable` property is set to `YES` will reflect the disable mode automatically (no need to reload table view).
####How to hide a row or section when another rows value changes.
To hide a row or section you should set its hidden property. The easiest way of doing this is by setting a NSString to it. Let's say you want a section to hide if a previous row, which is a boolean switch, is set to 1 (or YES). Then you would do something like this:
```objc
section.hidden = [NSString stringWithFormat:@"$%@ == 1", previousRow];
```
That is all!
####What do I have to do to migrate from version 2.2.0 to 3.0.0?
The only thing that is not compatible with older versions is that the `disabled` property of the `XLFormRowDescriptor` is an `id` now. So you just have to add `@` before the values you set to it like this:
```objc
row.disabled = @YES; // before: row.disabled = YES;
```
Installation
--------------------------
@@ -774,7 +861,7 @@ Installation
The easiest way to use XLForm in your app is via [CocoaPods](http://cocoapods.org/ "CocoaPods").
1. Add the following line in the project's Podfile file:
`pod 'XLForm', '~> 2.1.0'`.
`pod 'XLForm', '~> 3.0.0'`.
2. Run the command `pod install` from the Podfile folder directory.
XLForm **has no** dependencies over other pods.
@@ -807,7 +894,16 @@ Requirements
Release Notes
--------------
Version 2.2.1 (master)
Version 3.0.0 (master)
* `hidden`, `disable` properties added to `XLFormRowDescriptor`. `@YES` `@NO` or a `NSPredicate` can be used to hide, disable de row.
* `hidden` property added to `XLFormSectionDescriptor`. `@YES` `@NO` or a `NSPredicate` can be used to hide the section.
* Added `XLFormRowDescriptorTypeCountDownTimerInline` and `XLFormRowDescriptorTypeCountDownTimer` row type with an example.
* Deleted `dateFormatter` property and added support to use the `NSValueTransformer` to convert the selected object to a NSString in the XLFormDateCell class.
* Added `XLFormRowDescriptorTypeCountDownTimerInline` and `XLFormRowDescriptorTypeCountDownTimer` row type with an example.
* Deleted `dateFormatter` property and added support to use the `NSValueTransformer` to convert the selected object to a NSString in the XLFormDateCell class.
* Added example in the ```Multivalued Sections examples``` of how to add dynamic sections with multiple rows.
Version 2.2.0
+1 -1
View File
@@ -3,5 +3,5 @@ xcodeproj 'XLForm Tests'
inhibit_all_warnings!
platform :ios, '7.0'
pod 'Expecta', '~> 0.2.4'
pod 'Expecta', '~> 0.3.0'
pod 'XLForm', :path => '../'
+6 -1
View File
@@ -16,6 +16,7 @@
3C5B9B7A1AC0BA33000AF1BA /* XLFormExampleTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C5B9B791AC0BA33000AF1BA /* XLFormExampleTest.m */; };
3C9817861AC30616003F6ABD /* UITextField+Test.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C9817851AC30616003F6ABD /* UITextField+Test.m */; };
803CF19E12514D00A5080A99 /* libPods.a in Frameworks */ = {isa = PBXBuildFile; fileRef = CEC7E8601D7342BFAF4C4060 /* libPods.a */; };
BFD111841AD8323900943D23 /* XLTestHideAndShow.m in Sources */ = {isa = PBXBuildFile; fileRef = BFD111831AD8323900943D23 /* XLTestHideAndShow.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -33,6 +34,7 @@
3C9817841AC30616003F6ABD /* UITextField+Test.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "UITextField+Test.h"; path = "Helpers/UITextField+Test.h"; sourceTree = "<group>"; };
3C9817851AC30616003F6ABD /* UITextField+Test.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = "UITextField+Test.m"; path = "Helpers/UITextField+Test.m"; sourceTree = "<group>"; };
8ADC094C94CA7ABBB8134573 /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = "<group>"; };
BFD111831AD8323900943D23 /* XLTestHideAndShow.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLTestHideAndShow.m; path = Test/XLTestHideAndShow.m; sourceTree = "<group>"; };
C6B20EA1A9D9591335BEE81F /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = "<group>"; };
CEC7E8601D7342BFAF4C4060 /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -104,6 +106,7 @@
28657A4F19914F7000CE8180 /* Tests */ = {
isa = PBXGroup;
children = (
BFD111831AD8323900943D23 /* XLTestHideAndShow.m */,
3C5B9B791AC0BA33000AF1BA /* XLFormExampleTest.m */,
28657A5019914F9700CE8180 /* XLTestCase.h */,
28657A5119914F9700CE8180 /* XLTestCase.m */,
@@ -158,7 +161,7 @@
28657A3019907FBE00CE8180 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
LastUpgradeCheck = 0610;
};
buildConfigurationList = 28657A3319907FBE00CE8180 /* Build configuration list for PBXProject "XLForm Tests" */;
compatibilityVersion = "Xcode 3.2";
@@ -228,6 +231,7 @@
files = (
28657A54199154EE00CE8180 /* XLFormValidatorsTests.m in Sources */,
28657A5219914F9700CE8180 /* XLTestCase.m in Sources */,
BFD111841AD8323900943D23 /* XLTestHideAndShow.m in Sources */,
3C5B9B7A1AC0BA33000AF1BA /* XLFormExampleTest.m in Sources */,
3C9817861AC30616003F6ABD /* UITextField+Test.m in Sources */,
);
@@ -250,6 +254,7 @@
28657A3419907FBE00CE8180 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ONLY_ACTIVE_ARCH = YES;
};
name = Debug;
};
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "0510"
LastUpgradeVersion = "0610"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
@@ -49,6 +49,15 @@
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
allowLocationSimulation = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "28657A391990879200CE8180"
BuildableName = "XLForm Tests.xctest"
BlueprintName = "XLForm Tests"
ReferencedContainer = "container:XLForm Tests.xcodeproj">
</BuildableReference>
</MacroExpansion>
<AdditionalOptions>
</AdditionalOptions>
</LaunchAction>
+27 -50
View File
@@ -13,25 +13,11 @@
static NSString * const kTextFieldCellTag = @"TextFieldCellTag";
@interface XLFormExampleTest : XCTestCase
@property (nonatomic, strong) XLFormViewController * formController;
@interface XLFormExampleTest : XLTestCase
@end
@implementation XLFormExampleTest
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
[self buildForm]; // Build a form
[self forceLoadingOfTheView]; // Load the view
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testTableViewLoad
{
@@ -42,7 +28,7 @@ static NSString * const kTextFieldCellTag = @"TextFieldCellTag";
expect([tableView numberOfSections]).to.equal(1);
expect([tableView numberOfRowsInSection:0]).to.equal(1);
UITableViewCell * cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
UITableViewCell * cell = [self.formController tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
// Check if the cell match with the XLFormRowDescriptorTypeText
expect(cell).to.beKindOf([XLFormTextFieldCell class]);
XLFormTextFieldCell * textFieldCell = (XLFormTextFieldCell *)cell;
@@ -72,52 +58,43 @@ static NSString * const kTextFieldCellTag = @"TextFieldCellTag";
expect([tableView numberOfRowsInSection:1]).to.equal(1);
// Check if the cell match with the XLFormRowDescriptorTypeBooleanSwitch
UITableViewCell * cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
UITableViewCell * cell = [self.formController tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]];
expect(cell).to.beKindOf([XLFormSwitchCell class]);
}
- (void)testFillTextFieldCell
{
// Get the tableView
UITableView * tableView = self.formController.tableView;
// Get the cell that correspond to the row descriptor XLFormRowDescriptorTypeText
UITableViewCell * cell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
XLFormTextFieldCell * textFieldCell = (XLFormTextFieldCell *)cell;
// Get the texfield in the cell
UITextField * textField = textFieldCell.textField;
// Simulate that change the text on the textfield
[textField changeText:@"Name"];
// Get the row descriptor XLFormRowDescriptorTypeText
XLFormRowDescriptor * row = [self.formController.form formRowWithTag:kTextFieldCellTag];
// Check if the text field match with the row descriptor value
expect(row.value).to.equal(@"Name");
}
//- (void)testFillTextFieldCell
//{
// // Get the tableView
// UITableView * tableView = self.formController.tableView;
//
// // Get the cell that correspond to the row descriptor XLFormRowDescriptorTypeText
// UITableViewCell * cell = [self.formController tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
// XLFormTextFieldCell * textFieldCell = (XLFormTextFieldCell *)cell;
// // Get the texfield in the cell
// UITextField * textField = textFieldCell.textField;
//
// // Simulate that change the text on the textfield
// [textField changeText:@"Name"];
//
// // Get the row descriptor XLFormRowDescriptorTypeText
// XLFormRowDescriptor * row = [self.formController.form formRowWithTag:kTextFieldCellTag];
//
// // Check if the text field match with the row descriptor value
// expect(row.value).to.equal(@"Name");
//}
#pragma mark - Build Form
-(void)buildForm
{
self.formController = [[XLFormViewController alloc] init];
self.formController.form = [XLFormDescriptor formDescriptor];
XLFormDescriptor * form = [XLFormDescriptor formDescriptor];
XLFormSectionDescriptor * section = [XLFormSectionDescriptor formSection];
[self.formController.form addFormSection:section];
[form addFormSection:section];
XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:kTextFieldCellTag rowType:XLFormRowDescriptorTypeText title:@"Title"];
[section addFormRow:row];
self.formController.form = form;
}
#pragma mark - Load View
- (void)forceLoadingOfTheView
{
// This triggers to load the view
expect(self.formController.view).notTo.beNil();
}
@end
@@ -39,18 +39,15 @@
-(void)buildForm
{
self.formController = [[XLFormViewController alloc] init];
self.formController.form = [XLFormDescriptor formDescriptor];
XLFormDescriptor * form = [XLFormDescriptor formDescriptor];
XLFormSectionDescriptor * section = [XLFormSectionDescriptor formSection];
[self.formController.form addFormSection:section];
[form addFormSection:section];
XLFormRowDescriptor * row;
row = [XLFormRowDescriptor formRowDescriptorWithTag:XLFormRowDescriptorTypeText rowType:XLFormRowDescriptorTypeText title:@"Required XLFormRowDescriptorTypeText"];
XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:XLFormRowDescriptorTypeText rowType:XLFormRowDescriptorTypeText title:@"Title"];
row.required = YES;
[section addFormRow:row];
self.formController.form = form;
}
@end
+3
View File
@@ -12,9 +12,12 @@
#import "Expecta.h"
#import <XLForm/XLForm.h>
#import <XLForm/NSString+XLFormAdditions.h>
@interface XLTestCase : XCTestCase
@property (nonatomic, strong) XLFormViewController * formController;
-(void)buildForm;
@end
+39
View File
@@ -10,4 +10,43 @@
@implementation XLTestCase
- (void)setUp {
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
[self buildForm];
[self forceLoadingOfTheView]; // Load the view
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
self.formController = nil;
[super tearDown];
}
#pragma mark - Helpers
-(void)buildForm
{
}
-(XLFormViewController *)formController
{
if (_formController) return _formController;
_formController = [[XLFormViewController alloc] init];
return _formController;
}
- (void)forceLoadingOfTheView
{
// This triggers to load the view
expect(self.formController.view).notTo.beNil();
self.formController.view.frame = CGRectMake(0, 0, 375, 667);
[self.formController.view layoutIfNeeded];
// [self.formController.tableView reloadData];
}
@end
+115
View File
@@ -0,0 +1,115 @@
//
// testHideAndShow.m
// XLForm Tests
//
// Created by mathias Claassen on 10/4/15.
//
//
#import <UIKit/UIKit.h>
#import "XLTestCase.h"
static NSString * const kTextFieldCellTag = @"TextTag";
static NSString * const kIntegerFieldCellTag = @"IntegerTag";
static NSString * const kDisabledFieldCellTag = @"DisabledTag";
@interface XLFormDescriptor (_XLTestAdditions)
@property (readonly) NSMutableDictionary* allRowsByTag;
@property NSMutableDictionary* rowObservers;
@end
@interface XLTestHideAndShow : XLTestCase
@end
@implementation XLTestHideAndShow
- (void)testBasicPredicates {
// Get the tableView
UITableView * tableView = self.formController.tableView;
// Check if the tableView matches with the form descriptor
expect([tableView numberOfSections]).to.equal(2);
expect([tableView numberOfRowsInSection:0]).to.equal(2);
XLFormTextFieldCell * textFieldCell = (XLFormTextFieldCell*) [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
XLFormTextFieldCell * disabledFieldCell = (XLFormTextFieldCell*) [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]];
//Let's disable the row of the second section. The second row of the first section should hide.
textFieldCell.rowDescriptor.value = @"dis";
expect(disabledFieldCell.rowDescriptor.isDisabled).to.beTruthy;
expect([tableView numberOfSections]).to.equal(2);
expect([tableView numberOfRowsInSection:0]).to.equal(1);
// Now hide the second section. As the row will be enabled, the second row of the first section should reappear
textFieldCell.rowDescriptor.value = @"hide that section";
expect(disabledFieldCell.rowDescriptor.isDisabled).to.beFalsy;
expect([tableView numberOfSections]).to.equal(1);
expect([tableView numberOfRowsInSection:0]).to.equal(2);
//Now we disable the last row (even if its hidden) and consecuently the second row hides again.
textFieldCell.rowDescriptor.value = @"dishide";
expect([tableView numberOfSections]).to.equal(1);
expect([tableView numberOfRowsInSection:0]).to.equal(1);
//Now everything should be as at the beginning
textFieldCell.rowDescriptor.value = @"Hello World";
expect([tableView numberOfSections]).to.equal(2);
expect([tableView numberOfRowsInSection:0]).to.equal(2);
}
-(void)testInternalDataStructures{
UITableView * tableView = self.formController.tableView;
XLFormRowDescriptor* disabledRow = ((XLFormTextFieldCell*) [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1]]).rowDescriptor;
NSMutableDictionary* deps = self.formController.form.rowObservers;
NSMutableDictionary* rows = self.formController.form.allRowsByTag;
expect(rows[kDisabledFieldCellTag]).to.equal(disabledRow);
expect(rows[kIntegerFieldCellTag]).to.equal(((XLFormTextFieldCell*) [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]).rowDescriptor);
expect(rows[kTextFieldCellTag]).to.equal(((XLFormTextFieldCell*) [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]]).rowDescriptor);
expect(deps[[kDisabledFieldCellTag formKeyForPredicateType:XLPredicateTypeHidden ]]).to.equal(@[kIntegerFieldCellTag]);
expect(deps[[kIntegerFieldCellTag formKeyForPredicateType:XLPredicateTypeHidden ]]).to.equal(nil);
expect(deps[[kTextFieldCellTag formKeyForPredicateType:XLPredicateTypeHidden]]).to.equal(@[disabledRow.sectionDescriptor]);
expect(deps[[kTextFieldCellTag formKeyForPredicateType:XLPredicateTypeDisabled]]).to.equal(@[kDisabledFieldCellTag]);
}
#pragma mark - Build Form
-(void)buildForm
{
XLFormDescriptor * form = [XLFormDescriptor formDescriptor];
self.formController.form = form;
XLFormSectionDescriptor * section = [XLFormSectionDescriptor formSection];
[self.formController.form addFormSection:section];
XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:kTextFieldCellTag rowType:XLFormRowDescriptorTypeText title:@"Title"];
[section addFormRow:row];
XLFormRowDescriptor * row2 = [XLFormRowDescriptor formRowDescriptorWithTag:kIntegerFieldCellTag rowType:XLFormRowDescriptorTypeInteger title:@"Number"];
row2.hidden = [NSString stringWithFormat:@"$%@.isDisabled == 1", kDisabledFieldCellTag];
[section addFormRow:row2];
XLFormSectionDescriptor * section2 = [XLFormSectionDescriptor formSection];
section2.hidden = [NSString stringWithFormat:@"$%@ contains[c] 'hide'", row];
[self.formController.form addFormSection:section2];
XLFormRowDescriptor * row3 = [XLFormRowDescriptor formRowDescriptorWithTag:kDisabledFieldCellTag rowType:XLFormRowDescriptorTypeEmail title:@"Email"];
row3.disabled = [NSString stringWithFormat:@"$%@ contains[c] 'dis'", row];
[section2 addFormRow:row3];
}
@end
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'XLForm'
s.version = '2.2.0'
s.version = '3.0.0'
s.license = { :type => 'MIT' }
s.summary = 'XLForm is the most flexible and powerful iOS library to create dynamic table-view forms.'
s.description = <<-DESC
@@ -8,7 +8,7 @@ Pod::Spec.new do |s|
DESC
s.homepage = 'https://github.com/xmartlabs/XLForm'
s.authors = { 'Martin Barreto' => 'martin@xmartlabs.com' }
s.source = { :git => 'https://github.com/xmartlabs/XLForm.git', :tag => 'v2.2.0' }
s.source = { :git => 'https://github.com/xmartlabs/XLForm.git', :tag => 'v3.0.0' }
s.source_files = 'XLForm/XL/**/*.{h,m}'
s.requires_arc = true
s.ios.deployment_target = '7.0'
+1 -25
View File
@@ -70,7 +70,7 @@
{
self.textLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
self.detailTextLabel.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
self.textLabel.textColor = self.rowDescriptor.disabled ? [UIColor grayColor] : [UIColor blackColor];
self.textLabel.textColor = self.rowDescriptor.isDisabled ? [UIColor grayColor] : [UIColor blackColor];
}
-(void)highlight
@@ -129,28 +129,4 @@
return result;
}
#pragma mark -
-(void)setAccessoryType:(UITableViewCellAccessoryType)accessoryType
{
[super setAccessoryType:accessoryType];
[super setEditingAccessoryType:accessoryType];
}
-(void)setAccessoryView:(UIView *)accessoryView
{
[super setAccessoryView:accessoryView];
[super setEditingAccessoryView:accessoryView];
}
-(void)setEditingAccessoryType:(UITableViewCellAccessoryType)editingAccessoryType
{
[self setAccessoryType:editingAccessoryType];
}
-(void)setEditingAccessoryView:(UIView *)editingAccessoryView
{
[self setAccessoryView:editingAccessoryView];
}
@end
+2 -1
View File
@@ -48,7 +48,8 @@
self.textLabel.text = self.rowDescriptor.title;
BOOL leftAligmnment = self.rowDescriptor.action.viewControllerClass || [self.rowDescriptor.action.viewControllerStoryboardId length] != 0 || [self.rowDescriptor.action.viewControllerNibName length] != 0 || [self.rowDescriptor.action.formSegueIdenfifier length] != 0 || self.rowDescriptor.action.formSegueClass;
self.textLabel.textAlignment = leftAligmnment ? NSTextAlignmentLeft : NSTextAlignmentCenter;
self.accessoryType = !leftAligmnment || isDisabled ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator;
self.accessoryType = !leftAligmnment || isDisabled ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator;;
self.editingAccessoryType = self.accessoryType;
self.selectionStyle = isDisabled ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault;
}
+3 -2
View File
@@ -33,6 +33,7 @@
{
[super configure];
self.accessoryType = UITableViewCellAccessoryCheckmark;
self.editingAccessoryType = self.accessoryType;
}
- (void)update
@@ -40,11 +41,11 @@
[super update];
self.textLabel.text = self.rowDescriptor.title;
self.accessoryType = [self.rowDescriptor.value boolValue] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
self.editingAccessoryType = self.accessoryType;
CGFloat red, green, blue, alpha;
[self.tintColor getRed:&red green:&green blue:&blue alpha:&alpha];
self.selectionStyle = UITableViewCellSelectionStyleDefault;
if (self.rowDescriptor.isDisabled)
{
if (self.rowDescriptor.isDisabled){
[self setTintColor:[UIColor colorWithRed:red green:green blue:blue alpha:0.3]];
self.selectionStyle = UITableViewCellSelectionStyleNone;
}
-1
View File
@@ -34,7 +34,6 @@ typedef NS_ENUM(NSUInteger, XLFormDateDatePickerMode) {
@interface XLFormDateCell : XLFormBaseCell
@property (nonatomic) NSDateFormatter * dateFormatter;
@property (nonatomic) XLFormDateDatePickerMode formDatePickerMode;
@property (nonatomic) NSDate *minimumDate;
@property (nonatomic) NSDate *maximumDate;
+22 -13
View File
@@ -28,7 +28,6 @@
#import "XLFormRowDescriptor.h"
#import "XLFormDateCell.h"
@interface XLFormDateCell()
@property (nonatomic) UIDatePicker *datePicker;
@@ -43,7 +42,7 @@
- (UIView *)inputView
{
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDate] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTime] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTime]){
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDate] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTime] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTime] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimer]){
if (self.rowDescriptor.value){
[self.datePicker setDate:self.rowDescriptor.value];
}
@@ -55,7 +54,7 @@
- (BOOL)canBecomeFirstResponder
{
return (!self.rowDescriptor.isDisabled);
return !self.rowDescriptor.isDisabled;
}
-(BOOL)becomeFirstResponder
@@ -63,7 +62,7 @@
_beforeChangeColor = self.detailTextLabel.textColor;
BOOL result = [super becomeFirstResponder];
if (result){
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline])
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimerInline])
{
NSIndexPath * selectedRowPath = [self.formViewController.form indexPathOfFormRow:self.rowDescriptor];
NSIndexPath * nextRowPath = [NSIndexPath indexPathForRow:(selectedRowPath.row + 1) inSection:selectedRowPath.section];
@@ -74,8 +73,6 @@
if (self.rowDescriptor.value){
[datePickerCell.datePicker setDate:self.rowDescriptor.value];
}
[datePickerCell.datePicker addTarget:self action:@selector(datePickerValueChanged:) forControlEvents:UIControlEventValueChanged];
NSAssert([datePickerCell conformsToProtocol:@protocol(XLFormInlineRowDescriptorCell)], @"inline cell must conform to XLFormInlineRowDescriptorCell");
UITableViewCell<XLFormInlineRowDescriptorCell> * inlineCell = (UITableViewCell<XLFormInlineRowDescriptorCell> *)datePickerCell;
inlineCell.inlineRowDescriptor = self.rowDescriptor;
@@ -88,15 +85,14 @@
-(BOOL)resignFirstResponder
{
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline])
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimerInline])
{
NSIndexPath * selectedRowPath = [self.formViewController.form indexPathOfFormRow:self.rowDescriptor];
NSIndexPath * nextRowPath = [NSIndexPath indexPathForRow:selectedRowPath.row + 1 inSection:selectedRowPath.section];
XLFormRowDescriptor * nextFormRow = [self.formViewController.form formRowAtIndex:nextRowPath];
BOOL result = [super resignFirstResponder];
if ([nextFormRow.rowType isEqualToString:XLFormRowDescriptorTypeDatePicker]){
XLFormSectionDescriptor * formSection = [self.formViewController.form.formSections objectAtIndex:nextRowPath.section];
[formSection removeFormRow:nextFormRow];
[self.rowDescriptor.sectionDescriptor removeFormRow:nextFormRow];
}
return result;
}
@@ -115,6 +111,7 @@
{
[super update];
self.accessoryType = UITableViewCellAccessoryNone;
self.editingAccessoryType = UITableViewCellAccessoryNone;
[self.textLabel setText:self.rowDescriptor.title];
self.selectionStyle = self.rowDescriptor.isDisabled ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault;
self.textLabel.text = [NSString stringWithFormat:@"%@%@", self.rowDescriptor.title, self.rowDescriptor.required && self.rowDescriptor.sectionDescriptor.formDescriptor.addAsteriskToRequiredRowsTitle ? @"*" : @""];
@@ -163,8 +160,13 @@
- (NSString *)formattedDate:(NSDate *)date
{
if (self.dateFormatter){
return [self.dateFormatter stringFromDate:date];
if (self.rowDescriptor.valueTransformer){
NSAssert([self.rowDescriptor.valueTransformer isSubclassOfClass:[NSValueTransformer class]], @"valueTransformer is not a subclass of NSValueTransformer");
NSValueTransformer * valueTransformer = [self.rowDescriptor.valueTransformer new];
NSString * tranformedValue = [valueTransformer transformedValue:self.rowDescriptor.value];
if (tranformedValue){
return tranformedValue;
}
}
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDate] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline]){
return [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterNoStyle];
@@ -172,6 +174,10 @@
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTime] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline]){
return [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterNoStyle timeStyle:NSDateFormatterShortStyle];
}
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimer] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimerInline]){
NSDateComponents *time = [[NSCalendar currentCalendar] components:NSCalendarUnitHour | NSCalendarUnitMinute fromDate:date];
return [NSString stringWithFormat:@"%ld%@ %ldmin", (long)[time hour], (long)[time hour] == 1 ? @"hour" : @"hours", (long)[time minute]];
}
return [NSDateFormatter localizedStringFromDate:date dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle];
}
@@ -183,6 +189,9 @@
else if ((([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTime]) && self.formDatePickerMode == XLFormDateDatePickerModeGetFromRowDescriptor) || self.formDatePickerMode == XLFormDateDatePickerModeTime){
datePicker.datePickerMode = UIDatePickerModeTime;
}
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimer] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimerInline]){
datePicker.datePickerMode = UIDatePickerModeCountDownTimer;
}
else{
datePicker.datePickerMode = UIDatePickerModeDateAndTime;
}
@@ -213,8 +222,8 @@
- (void)datePickerValueChanged:(UIDatePicker *)sender
{
self.detailTextLabel.text = [self formattedDate:sender.date];
self.rowDescriptor.value = sender.date;
self.detailTextLabel.text = [self valueDisplayText];
[self setNeedsLayout];
}
@@ -223,7 +232,7 @@
{
_formDatePickerMode = formDatePickerMode;
if ([self isFirstResponder]){
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline])
if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeDateTimeInline] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeCountDownTimerInline])
{
NSIndexPath * selectedRowPath = [self.formViewController.form indexPathOfFormRow:self.rowDescriptor];
NSIndexPath * nextRowPath = [NSIndexPath indexPathForRow:selectedRowPath.row + 1 inSection:selectedRowPath.section];
+16
View File
@@ -43,9 +43,24 @@
{
if (_datePicker) return _datePicker;
_datePicker = [UIDatePicker autolayoutView];
[_datePicker addTarget:self action:@selector(datePickerValueChanged:) forControlEvents:UIControlEventValueChanged];
return _datePicker;
}
#pragma mark- Target Action
- (void)datePickerValueChanged:(UIDatePicker *)sender
{
if (self.inlineRowDescriptor){
self.inlineRowDescriptor.value = sender.date;
[self.formViewController updateFormRow:self.inlineRowDescriptor];
}
else{
[self becomeFirstResponder];
self.rowDescriptor.value = sender.date;
}
}
#pragma mark - XLFormDescriptorCell
-(void)configure
@@ -59,6 +74,7 @@
-(void)update
{
[super update];
[self.datePicker setUserInteractionEnabled:![self.rowDescriptor isDisabled]];
}
+2 -1
View File
@@ -78,6 +78,7 @@
{
[super update];
self.accessoryType = UITableViewCellAccessoryNone;
self.editingAccessoryType = UITableViewCellAccessoryNone;
[self.textLabel setText:self.rowDescriptor.title];
self.selectionStyle = self.rowDescriptor.isDisabled ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault;
self.textLabel.text = [NSString stringWithFormat:@"%@%@", self.rowDescriptor.title, self.rowDescriptor.required && self.rowDescriptor.sectionDescriptor.formDescriptor.addAsteriskToRequiredRowsTitle ? @"*" : @""];
@@ -86,7 +87,7 @@
-(BOOL)formDescriptorCellCanBecomeFirstResponder
{
return (!self.rowDescriptor.disabled);
return !(self.rowDescriptor.isDisabled);
}
-(BOOL)formDescriptorCellBecomeFirstResponder
+2 -1
View File
@@ -136,8 +136,9 @@
[self.leftButton setTitle:[NSString stringWithFormat:@"%@%@", [self.rowDescriptor.leftRightSelectorLeftOptionSelected displayText], self.rowDescriptor.required && self.rowDescriptor.sectionDescriptor.formDescriptor.addAsteriskToRequiredRowsTitle ? @"*" : @""] forState:UIControlStateNormal];
[self.rowDescriptor setTitle:[self.rowDescriptor.leftRightSelectorLeftOptionSelected displayText]];
self.rightLabel.text = [self rightTextLabel];
[self.leftButton setEnabled:(!self.rowDescriptor.isDisabled)];
[self.leftButton setEnabled:!self.rowDescriptor.isDisabled];
self.accessoryView = self.rowDescriptor.isDisabled ? nil : [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"XLForm.bundle/forwardarrow.png"]];
self.editingAccessoryView = self.accessoryView;
self.selectionStyle = self.rowDescriptor.isDisabled ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault;
}
+1 -1
View File
@@ -37,7 +37,7 @@
-(BOOL)formDescriptorCellCanBecomeFirstResponder
{
return ((!self.rowDescriptor.isDisabled) && (self.inlineRowDescriptor == nil));
return (!self.rowDescriptor.isDisabled && (self.inlineRowDescriptor == nil));
}
-(BOOL)formDescriptorCellBecomeFirstResponder
+3 -2
View File
@@ -101,7 +101,7 @@
-(BOOL)formDescriptorCellCanBecomeFirstResponder
{
return ((!self.rowDescriptor.isDisabled) && ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorPickerView]));
return (!self.rowDescriptor.isDisabled && ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorPickerView]));
}
-(BOOL)formDescriptorCellBecomeFirstResponder
@@ -139,7 +139,8 @@
-(void)update
{
[super update];
self.accessoryType = self.rowDescriptor.isDisabled || !([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorPush] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelector]) ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator;
self.accessoryType = self.rowDescriptor.isDisabled || !([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorPush] || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelector]) ? UITableViewCellAccessoryNone : UITableViewCellAccessoryDisclosureIndicator;;
self.editingAccessoryType = self.accessoryType;
[self.textLabel setText:self.rowDescriptor.title];
self.selectionStyle = self.rowDescriptor.isDisabled || [self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeInfo] ? UITableViewCellSelectionStyleNone : UITableViewCellSelectionStyleDefault;
self.textLabel.text = [NSString stringWithFormat:@"%@%@", self.rowDescriptor.title, self.rowDescriptor.required && self.rowDescriptor.sectionDescriptor.formDescriptor.addAsteriskToRequiredRowsTitle ? @"*" : @""];
+1
View File
@@ -66,6 +66,7 @@
[container addSubview:currentStepValue];
self.accessoryView = container;
self.editingAccessoryView = container;
}
- (void)update
+1
View File
@@ -36,6 +36,7 @@
[super configure];
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.accessoryView = [[UISwitch alloc] init];
self.editingAccessoryView = self.accessoryView;
[self.switchControl addTarget:self action:@selector(valueChanged) forControlEvents:UIControlEventValueChanged];
}
@@ -28,6 +28,28 @@
#import "XLFormViewController.h"
#import "UIView+XLFormAdditions.h"
#import "XLForm.h"
#import "NSString+XLFormAdditions.h"
@interface XLFormRowDescriptor(_XLFormViewController)
@property (readonly) NSArray * observers;
-(BOOL)evaluateIsDisabled;
-(BOOL)evaluateIsHidden;
@end
@interface XLFormSectionDescriptor(_XLFormViewController)
-(BOOL)evaluateIsHidden;
@end
@interface XLFormDescriptor (_XLFormViewController)
@property NSMutableDictionary* rowObservers;
@end
@interface XLFormViewController()
@@ -140,6 +162,7 @@
selector:@selector(keyboardWillHide:)
name:UIKeyboardWillHideNotification
object:nil];
}
-(void)viewDidDisappear:(BOOL)animated
@@ -206,9 +229,11 @@
XLFormRowDescriptorTypeDate: [XLFormDateCell class],
XLFormRowDescriptorTypeTime: [XLFormDateCell class],
XLFormRowDescriptorTypeDateTime : [XLFormDateCell class],
XLFormRowDescriptorTypeCountDownTimer : [XLFormDateCell class],
XLFormRowDescriptorTypeDateInline: [XLFormDateCell class],
XLFormRowDescriptorTypeTimeInline: [XLFormDateCell class],
XLFormRowDescriptorTypeDateTimeInline: [XLFormDateCell class],
XLFormRowDescriptorTypeCountDownTimerInline : [XLFormDateCell class],
XLFormRowDescriptorTypeDatePicker : [XLFormDatePickerCell class],
XLFormRowDescriptorTypePicker : [XLFormPickerCell class],
XLFormRowDescriptorTypeSlider : [XLFormSliderCell class],
@@ -241,26 +266,68 @@
-(void)formRowHasBeenAdded:(XLFormRowDescriptor *)formRow atIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:[self insertRowAnimationForRow:formRow]];
[self.tableView endUpdates];
}
-(void)formRowHasBeenRemoved:(XLFormRowDescriptor *)formRow atIndexPath:(NSIndexPath *)indexPath
{
[self.tableView beginUpdates];
[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:[self deleteRowAnimationForRow:formRow]];
[self.tableView endUpdates];
}
-(void)formSectionHasBeenRemoved:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index
{
[self.tableView beginUpdates];
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:index] withRowAnimation:[self deleteRowAnimationForSection:formSection]];
[self.tableView endUpdates];
}
-(void)formSectionHasBeenAdded:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index
{
[self.tableView beginUpdates];
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:index] withRowAnimation:[self insertRowAnimationForSection:formSection]];
[self.tableView endUpdates];
}
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue
{
[self updateAfterDependentRowChanged:formRow];
}
-(void)formRowDescriptorPredicateHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue predicateType:(XLPredicateType)predicateType
{
if (oldValue != newValue) {
[self updateAfterDependentRowChanged:formRow];
}
}
-(void)updateAfterDependentRowChanged:(XLFormRowDescriptor *)formRow{
NSMutableArray* revaluateHidden = self.form.rowObservers[[formRow.tag formKeyForPredicateType:XLPredicateTypeHidden]];
NSMutableArray* revaluateDisabled = self.form.rowObservers[[formRow.tag formKeyForPredicateType:XLPredicateTypeDisabled]];
for (id object in revaluateDisabled) {
if ([object isKindOfClass:[NSString class]]) {
XLFormRowDescriptor* row = [self.form formRowWithTag:object];
if (row){
[row evaluateIsDisabled];
[self updateFormRow:row];
}
}
}
for (id object in revaluateHidden) {
if ([object isKindOfClass:[NSString class]]) {
XLFormRowDescriptor* row = [self.form formRowWithTag:object];
if (row){
[row evaluateIsHidden];
}
}
else if ([object isKindOfClass:[XLFormSectionDescriptor class]]) {
XLFormSectionDescriptor* section = (XLFormSectionDescriptor*) object;
[section evaluateIsHidden];
}
}
}
#pragma mark - XLFormViewControllerDelegate
@@ -868,6 +935,7 @@
{
_form = form;
_form.delegate = self;
[_form forceEvaluate];
}
-(XLFormDescriptor *)form
+5 -3
View File
@@ -28,8 +28,8 @@
#import "XLFormDescriptorDelegate.h"
#import <Foundation/Foundation.h>
NSString * const XLFormErrorDomain;
NSString * const XLValidationStatusErrorKey;
extern NSString * const XLFormErrorDomain;
extern NSString * const XLValidationStatusErrorKey;
typedef NS_ENUM(NSInteger, XLFormErrorCode)
{
@@ -64,6 +64,7 @@ typedef NS_OPTIONS(NSUInteger, XLFormRowNavigationOptions) {
-(void)addFormSection:(XLFormSectionDescriptor *)formSection;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection beforeSection:(XLFormSectionDescriptor *)beforeSection;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection afterSection:(XLFormSectionDescriptor *)afterSection;
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRowTag:(NSString *)afterRowTag;
@@ -74,7 +75,6 @@ typedef NS_OPTIONS(NSUInteger, XLFormRowNavigationOptions) {
-(void)removeFormRow:(XLFormRowDescriptor *)formRow;
-(void)removeFormRowWithTag:(NSString *)tag;
-(XLFormRowDescriptor *)formRowWithTag:(NSString *)tag;
-(XLFormRowDescriptor *)formRowAtIndex:(NSIndexPath *)indexPath;
-(XLFormRowDescriptor *)formRowWithHash:(NSUInteger)hash;
@@ -91,4 +91,6 @@ typedef NS_OPTIONS(NSUInteger, XLFormRowNavigationOptions) {
-(XLFormRowDescriptor *)nextRowDescriptorForRow:(XLFormRowDescriptor *)currentRow;
-(XLFormRowDescriptor *)previousRowDescriptorForRow:(XLFormRowDescriptor *)currentRow;
-(void)forceEvaluate;
@end
+263 -54
View File
@@ -26,14 +26,36 @@
#import "NSObject+XLFormAdditions.h"
#import "XLFormDescriptor.h"
#import "NSPredicate+XLFormAdditions.h"
#import "NSString+XLFormAdditions.h"
NSString * const XLFormErrorDomain = @"XLFormErrorDomain";
NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
@interface XLFormSectionDescriptor (_XLFormDescriptor)
@property NSArray * allRows;
-(BOOL)evaluateIsHidden;
@end
@interface XLFormRowDescriptor(_XLFormDescriptor)
-(BOOL)evaluateIsDisabled;
-(BOOL)evaluateIsHidden;
@end
@interface XLFormDescriptor()
@property NSMutableArray * formSections;
@property (readonly) NSMutableArray * allSections;
@property NSString * title;
@property (readonly) NSMutableDictionary* allRowsByTag;
@property NSMutableDictionary* rowObservers;
@end
@@ -49,6 +71,9 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
self = [super init];
if (self){
_formSections = [NSMutableArray array];
_allSections = [NSMutableArray array];
_allRowsByTag = [NSMutableDictionary dictionary];
_rowObservers = [NSMutableDictionary dictionary];
_title = title;
_addAsteriskToRequiredRowsTitle = NO;
_disabled = NO;
@@ -70,33 +95,62 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
-(void)addFormSection:(XLFormSectionDescriptor *)formSection
{
[self insertObject:formSection inFormSectionsAtIndex:[self.formSections count]];
[self insertObject:formSection inAllSectionsAtIndex:[self.allSections count]];
}
-(void)addFormSection:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index
{
if (self.formSections.count >= index) {
[self insertObject:formSection inFormSectionsAtIndex:index];
if (index == 0){
[self insertObject:formSection inAllSectionsAtIndex:0];
}
else{
XLFormSectionDescriptor* previousSection = [self.formSections objectAtIndex:MIN(self.formSections.count, index-1)];
[self addFormSection:formSection afterSection:previousSection];
}
}
-(void)addFormSection:(XLFormSectionDescriptor *)formSection afterSection:(XLFormSectionDescriptor *)afterSection
{
NSUInteger index = [self.formSections indexOfObject:afterSection];
if (index != NSNotFound) {
[self insertObject:formSection inFormSectionsAtIndex:[self.formSections indexOfObject:afterSection]+1];
NSUInteger sectionIndex;
NSUInteger allSectionIndex;
if ((sectionIndex = [self.allSections indexOfObject:formSection]) == NSNotFound){
allSectionIndex = [self.allSections indexOfObject:afterSection];
if (allSectionIndex != NSNotFound) {
[self insertObject:formSection inAllSectionsAtIndex:(allSectionIndex + 1)];
}
else { //case when afterSection does not exist. Just insert at the end.
[self addFormSection:formSection];
return;
}
}
formSection.hidden = formSection.hidden;
}
-(void)addFormSection:(XLFormSectionDescriptor *)formSection beforeSection:(XLFormSectionDescriptor *)afterSection
{
NSUInteger sectionIndex;
NSUInteger allSectionIndex;
if ((sectionIndex = [self.allSections indexOfObject:formSection]) == NSNotFound){
allSectionIndex = [self.allSections indexOfObject:afterSection];
if (allSectionIndex != NSNotFound) {
[self insertObject:formSection inAllSectionsAtIndex:allSectionIndex];
}
else { //case when afterSection does not exist. Just insert at the end.
[self addFormSection:formSection];
return;
}
}
formSection.hidden = formSection.hidden;
}
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)beforeRow
{
NSIndexPath * beforeIndexPath = [self indexPathOfFormRow:beforeRow];
if (self.formSections.count > beforeIndexPath.section){
[[self.formSections objectAtIndex:beforeIndexPath.section] addFormRow:formRow beforeRow:beforeRow];
if (beforeRow.sectionDescriptor){
[beforeRow.sectionDescriptor addFormRow:formRow beforeRow:beforeRow];
}
else{
[[self.formSections lastObject] addFormRow:formRow beforeRow:beforeRow];
[[self.allSections lastObject] addFormRow:formRow beforeRow:beforeRow];
}
}
@@ -110,12 +164,11 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
-(void)addFormRow:(XLFormRowDescriptor *)formRow afterRow:(XLFormRowDescriptor *)afterRow
{
NSIndexPath * afterIndexPath = [self indexPathOfFormRow:afterRow];
if (self.formSections.count > afterIndexPath.section){
[[self.formSections objectAtIndex:afterIndexPath.section] addFormRow:formRow afterRow:afterRow];
if (afterRow.sectionDescriptor){
[afterRow.sectionDescriptor addFormRow:formRow afterRow:afterRow];
}
else{
[[self.formSections lastObject] addFormRow:formRow afterRow:afterRow];
[[self.allSections lastObject] addFormRow:formRow afterRow:afterRow];
}
}
@@ -128,7 +181,10 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
-(void)removeFormSectionAtIndex:(NSUInteger)index
{
if (self.formSections.count > index){
XLFormSectionDescriptor *formSection = [self.formSections objectAtIndex:index];
[self removeObjectFromFormSectionsAtIndex:index];
NSUInteger allSectionIndex = [self.allSections indexOfObject:formSection];
[self removeObjectFromAllSectionsAtIndex:allSectionIndex];
}
}
@@ -137,6 +193,9 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
NSUInteger index = NSNotFound;
if ((index = [self.formSections indexOfObject:formSection]) != NSNotFound){
[self removeFormSectionAtIndex:index];
}
else if ((index = [self.allSections indexOfObject:formSection]) != NSNotFound){
[self removeObjectFromAllSectionsAtIndex:index];
};
}
@@ -149,23 +208,40 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
}
}
-(void)showFormSection:(XLFormSectionDescriptor*)formSection
{
NSUInteger formIndex = [self.formSections indexOfObject:formSection];
if (formIndex != NSNotFound) {
return;
}
NSUInteger index = [self.allSections indexOfObject:formSection];
if (index != NSNotFound){
while (formIndex == NSNotFound && index > 0) {
XLFormSectionDescriptor* previous = [self.allSections objectAtIndex:--index];
formIndex = [self.formSections indexOfObject:previous];
}
[self insertObject:formSection inFormSectionsAtIndex:(formIndex == NSNotFound ? 0 : ++formIndex)];
}
}
-(void)hideFormSection:(XLFormSectionDescriptor*)formSection
{
NSUInteger index = [self.formSections indexOfObject:formSection];
if (index != NSNotFound){
[self removeObjectFromFormSectionsAtIndex:index];
}
}
-(XLFormRowDescriptor *)formRowWithTag:(NSString *)tag
{
for (XLFormSectionDescriptor * section in self.formSections){
for (XLFormRowDescriptor * row in section.formRows) {
if ([row.tag isEqualToString:tag]){
return row;
}
}
}
return nil;
return self.allRowsByTag[tag];
}
-(XLFormRowDescriptor *)formRowWithHash:(NSUInteger)hash
{
for (XLFormSectionDescriptor * section in self.formSections){
for (XLFormRowDescriptor * row in section.formRows) {
for (XLFormSectionDescriptor * section in self.allSections){
for (XLFormRowDescriptor * row in section.allRows) {
if ([row hash] == hash){
return row;
}
@@ -209,6 +285,21 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
return nil;
}
-(NSIndexPath *)globalIndexPathOfFormRow:(XLFormRowDescriptor *)formRow
{
XLFormSectionDescriptor * section = formRow.sectionDescriptor;
if (section){
NSUInteger sectionIndex = [self.allSections indexOfObject:section];
if (sectionIndex != NSNotFound){
NSUInteger rowIndex = [section.allRows indexOfObject:formRow];
if (rowIndex != NSNotFound){
return [NSIndexPath indexPathForRow:rowIndex inSection:sectionIndex];
}
}
}
return nil;
}
-(NSDictionary *)formValues
{
NSMutableDictionary * result = [NSMutableDictionary dictionary];
@@ -224,7 +315,7 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
}
else{
for (XLFormRowDescriptor * row in section.formRows) {
if (row.tag && ![row.tag isEqualToString:@""]){
if (row.tag.length > 0){
[result setObject:(row.value ?: [NSNull null]) forKey:row.tag];
}
}
@@ -264,7 +355,7 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
if ([descriptorCell respondsToSelector:@selector(formDescriptorHttpParameterName)]){
return [descriptorCell formDescriptorHttpParameterName];
}
if (row.tag && ![row.tag isEqualToString:@""]){
if (row.tag.length > 0){
return row.tag;
}
return nil;
@@ -322,31 +413,10 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
[self.delegate formSectionHasBeenRemoved:removedSection atIndex:indexSet.firstIndex];
}
}
else if ([keyPath isEqualToString:@"formRows"]){
if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeInsertion)]){
NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
XLFormRowDescriptor * formRow = [((XLFormSectionDescriptor *)object).formRows objectAtIndex:indexSet.firstIndex];
NSUInteger sectionIndex = [self.formSections indexOfObject:object];
[self.delegate formRowHasBeenAdded:formRow atIndexPath:[NSIndexPath indexPathForRow:indexSet.firstIndex inSection:sectionIndex]];
}
else if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeRemoval)]){
NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
XLFormRowDescriptor * removedRow = [[change objectForKey:NSKeyValueChangeOldKey] objectAtIndex:0];
NSUInteger sectionIndex = [self.formSections indexOfObject:object];
[self.delegate formRowHasBeenRemoved:removedRow atIndexPath:[NSIndexPath indexPathForRow:indexSet.firstIndex inSection:sectionIndex]];
}
}
}
-(void)dealloc
{
for (XLFormSectionDescriptor * formSection in self.formSections) {
@try {
[formSection removeObserver:self forKeyPath:@"formRows"];
}
@catch (NSException * __unused exception) {}
}
@try {
[self removeObserver:self forKeyPath:@"formSections"];
}
@@ -369,23 +439,78 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
}
- (void)insertObject:(XLFormSectionDescriptor *)formSection inFormSectionsAtIndex:(NSUInteger)index {
formSection.formDescriptor = self;
[formSection addObserver:self forKeyPath:@"formRows" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:0];
[self.formSections insertObject:formSection atIndex:index];
}
- (void)removeObjectFromFormSectionsAtIndex:(NSUInteger)index {
XLFormSectionDescriptor * formSection = [self.formSections objectAtIndex:index];
@try {
[formSection removeObserver:self forKeyPath:@"formRows"];
}
@catch (NSException * __unused exception) {}
[self.formSections removeObjectAtIndex:index];
}
#pragma mark - allSections KVO
-(NSUInteger)countOfAllSections
{
return self.allSections.count;
}
- (id)objectInAllSectionsAtIndex:(NSUInteger)index {
return [self.allSections objectAtIndex:index];
}
- (NSArray *)allSectionsAtIndexes:(NSIndexSet *)indexes {
return [self.allSections objectsAtIndexes:indexes];
}
- (void)removeObjectFromAllSectionsAtIndex:(NSUInteger)index {
XLFormSectionDescriptor* section = [self.allSections objectAtIndex:index];
@try {
[section removeObserver:self forKeyPath:@"formRows"];
}
@catch (NSException * __unused exception) {}
[section.allRows enumerateObjectsUsingBlock:^(id obj, NSUInteger __unused idx, BOOL *stop) {
XLFormRowDescriptor * row = (id)obj;
[self removeObserversOfObject:row predicateType:XLPredicateTypeDisabled];
[self removeObserversOfObject:row predicateType:XLPredicateTypeHidden];
}];
[self removeObserversOfObject:section predicateType:XLPredicateTypeHidden];
[self.allSections removeObjectAtIndex:index];
}
- (void)insertObject:(XLFormSectionDescriptor *)section inAllSectionsAtIndex:(NSUInteger)index {
section.formDescriptor = self;
[self.allSections insertObject:section atIndex:index];
section.hidden = section.hidden;
[section.allRows enumerateObjectsUsingBlock:^(id obj, NSUInteger __unused idx, BOOL * __unused stop) {
XLFormRowDescriptor * row = (id)obj;
[self addRowToTagCollection:obj];
row.hidden = row.hidden;
row.disabled = row.disabled;
}];
}
#pragma mark - EvaluateForm
-(void)forceEvaluate
{
for (XLFormSectionDescriptor* section in self.allSections){
for (XLFormRowDescriptor* row in section.allRows) {
[self addRowToTagCollection:row];
}
}
for (XLFormSectionDescriptor* section in self.allSections){
for (XLFormRowDescriptor* row in section.allRows) {
[row evaluateIsDisabled];
[row evaluateIsHidden];
}
[section evaluateIsHidden];
}
}
#pragma mark - private
-(NSMutableArray *)formSections
{
return _formSections;
@@ -439,4 +564,88 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
return nil;
}
-(void)addRowToTagCollection:(XLFormRowDescriptor*) rowDescriptor
{
if (rowDescriptor.tag) {
self.allRowsByTag[rowDescriptor.tag] = rowDescriptor;
}
}
-(void)removeRowFromTagCollection:(XLFormRowDescriptor *)rowDescriptor
{
[self.allRowsByTag removeObjectForKey:rowDescriptor];
}
-(void)addObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType
{
NSPredicate* predicate;
id descriptor;
switch(predicateType){
case XLPredicateTypeHidden:
if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
predicate = ((XLFormRowDescriptor*)sectionOrRow).hidden;
}
else if ([sectionOrRow isKindOfClass:([XLFormSectionDescriptor class])]) {
descriptor = sectionOrRow;
predicate = ((XLFormSectionDescriptor*)sectionOrRow).hidden;
}
break;
case XLPredicateTypeDisabled:
if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
predicate = ((XLFormRowDescriptor*)sectionOrRow).disabled;
}
else return;
break;
}
NSMutableArray* tags = [predicate getPredicateVars];
for (NSString* tag in tags) {
NSString* auxTag = [tag formKeyForPredicateType:predicateType];
if (!self.rowObservers[auxTag]){
self.rowObservers[auxTag] = [NSMutableArray array];
}
if (![self.rowObservers[auxTag] containsObject:descriptor])
[self.rowObservers[auxTag] addObject:descriptor];
}
}
-(void)removeObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType
{
NSPredicate* predicate;
id descriptor;
switch(predicateType){
case XLPredicateTypeHidden:
if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
predicate = ((XLFormRowDescriptor*)sectionOrRow).hidden;
}
else if ([sectionOrRow isKindOfClass:([XLFormSectionDescriptor class])]) {
descriptor = sectionOrRow;
predicate = ((XLFormSectionDescriptor*)sectionOrRow).hidden;
}
break;
case XLPredicateTypeDisabled:
if ([sectionOrRow isKindOfClass:([XLFormRowDescriptor class])]) {
descriptor = ((XLFormRowDescriptor*)sectionOrRow).tag;
predicate = ((XLFormRowDescriptor*)sectionOrRow).disabled;
}
else return;
break;
}
if ([predicate isKindOfClass:[NSPredicate class] ]) {
NSMutableArray* tags = [predicate getPredicateVars];
for (NSString* tag in tags) {
NSString* auxTag = [tag formKeyForPredicateType:predicateType];
if (self.rowObservers[auxTag]){
[self.rowObservers[auxTag] removeObject:descriptor];
}
}
}
}
@end
@@ -23,12 +23,17 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "XLFormSectionDescriptor.h"
#import "XLFormDescriptor.h"
#import <Foundation/Foundation.h>
@class XLFormSectionDescriptor;
typedef NS_ENUM(NSUInteger, XLPredicateType) {
XLPredicateTypeDisabled = 0,
XLPredicateTypeHidden
};
@protocol XLFormDescriptorDelegate <NSObject>
@required
@@ -38,5 +43,9 @@
-(void)formRowHasBeenAdded:(XLFormRowDescriptor *)formRow atIndexPath:(NSIndexPath *)indexPath;
-(void)formRowHasBeenRemoved:(XLFormRowDescriptor *)formRow atIndexPath:(NSIndexPath *)indexPath;
-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue;
-(void)formRowDescriptorPredicateHasChanged:(XLFormRowDescriptor *)formRow
oldValue:(id)oldValue
newValue:(id)newValue
predicateType:(XLPredicateType)predicateType;
@end
+5 -1
View File
@@ -54,7 +54,11 @@ typedef NS_ENUM(NSUInteger, XLFormPresentationMode) {
@property (nonatomic) NSMutableDictionary *cellConfig;
@property (nonatomic) NSMutableDictionary *cellConfigIfDisabled;
@property (nonatomic) NSMutableDictionary *cellConfigAtConfigure;
@property (getter=isDisabled) BOOL disabled;
@property id disabled;
-(BOOL)isDisabled;
@property id hidden;
-(BOOL)isHidden;
@property (getter=isRequired) BOOL required;
@property XLFormAction * action;
+212 -22
View File
@@ -26,26 +26,58 @@
#import "XLForm.h"
#import "XLFormViewController.h"
#import "XLFormRowDescriptor.h"
#import "NSString+XLFormAdditions.h"
@interface XLFormDescriptor (_XLFormRowDescriptor)
@property (readonly) NSDictionary* allRowsByTag;
-(void)addObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
-(void)removeObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
@end
@interface XLFormSectionDescriptor (_XLFormRowDescriptor)
-(void)showFormRow:(XLFormRowDescriptor*)formRow;
-(void)hideFormRow:(XLFormRowDescriptor*)formRow;
@end
@interface XLFormRowDescriptor() <NSCopying>
@property XLFormBaseCell * cell;
@property (nonatomic) NSMutableArray *validators;
@property BOOL isDirtyDisablePredicateCache;
@property (nonatomic) NSNumber* disablePredicateCache;
@property BOOL isDirtyHidePredicateCache;
@property (nonatomic) NSNumber* hidePredicateCache;
@end
@implementation XLFormRowDescriptor
@synthesize action = _action;
@synthesize disabled = _disabled;
@synthesize hidden = _hidden;
@synthesize hidePredicateCache = _hidePredicateCache;
@synthesize disablePredicateCache = _disablePredicateCache;
-(id)init
{
@throw [NSException exceptionWithName:NSGenericException reason:@"initWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title must be used" userInfo:nil];
}
-(id)initWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title;
{
self = [self init];
self = [super init];
if (self){
NSAssert(((![rowType isEqualToString:XLFormRowDescriptorTypeSelectorPopover] && ![rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelectorPopover]) || (([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) && ([rowType isEqualToString:XLFormRowDescriptorTypeSelectorPopover] || [rowType isEqualToString:XLFormRowDescriptorTypeMultipleSelectorPopover]))), @"You must be running under UIUserInterfaceIdiomPad to use either XLFormRowDescriptorTypeSelectorPopover or XLFormRowDescriptorTypeMultipleSelectorPopover rows.");
_tag = tag;
_disabled = NO;
_disabled = @NO;
_hidden = @NO;
_rowType = rowType;
_title = title;
_cellStyle = UITableViewCellStyleValue1;
@@ -53,6 +85,13 @@
_cellConfig = [NSMutableDictionary dictionary];
_cellConfigIfDisabled = [NSMutableDictionary dictionary];
_cellConfigAtConfigure = [NSMutableDictionary dictionary];
_isDirtyDisablePredicateCache = YES;
_disablePredicateCache = nil;
_isDirtyHidePredicateCache = YES;
_hidePredicateCache = nil;
[self addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
[self addObserver:self forKeyPath:@"disablePredicateCache" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
[self addObserver:self forKeyPath:@"hidePredicateCache" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
}
return self;
}
@@ -69,19 +108,18 @@
-(XLFormBaseCell *)cellForFormController:(XLFormViewController *)formController
{
id cellClass = self.cellClass ?: [XLFormViewController cellClassesForRowDescriptorTypes][self.rowType];
NSAssert(cellClass, @"Not defined XLFormRowDescriptorType");
if (!_cell){
id cellClass = self.cellClass ?: [XLFormViewController cellClassesForRowDescriptorTypes][self.rowType];
NSAssert(cellClass, @"Not defined XLFormRowDescriptorType: %@", self.rowType ?: @"");
if ([cellClass isKindOfClass:[NSString class]]) {
if ([[NSBundle mainBundle] pathForResource:cellClass ofType:@"nib"]){
_cell = [[[NSBundle mainBundle] loadNibNamed:cellClass owner:nil options:nil] firstObject];
[self configureCellAtCreationTime];
}
} else if (!_cell) {
} else {
_cell = [[cellClass alloc] initWithStyle:self.cellStyle reuseIdentifier:nil];
[self configureCellAtCreationTime];
}
NSAssert([_cell isKindOfClass:[XLFormBaseCell class]], @"Can not get a XLFormBaseCell");
NSAssert([_cell isKindOfClass:[XLFormBaseCell class]], @"UITableViewCell must extend from XLFormBaseCell");
[self configureCellAtCreationTime];
}
return _cell;
}
@@ -116,7 +154,7 @@
-(NSString *)description
{
return [NSString stringWithFormat:@"%@ - %@ (%@)", [super description], self.tag, self.rowType];
return self.tag; // [NSString stringWithFormat:@"%@ - %@ (%@)", [super description], self.tag, self.rowType];
}
-(XLFormAction *)action
@@ -132,31 +170,24 @@
_action = action;
}
-(BOOL)isDisabled
{
return _disabled || self.sectionDescriptor.formDescriptor.isDisabled;
}
-(void)setDisabled:(BOOL)disabled
{
_disabled = disabled;
}
// In the implementation
-(id)copyWithZone:(NSZone *)zone
{
XLFormRowDescriptor * rowDescriptorCopy = [XLFormRowDescriptor formRowDescriptorWithTag:[self.tag copy] rowType:[self.rowType copy] title:[self.title copy]];
XLFormRowDescriptor * rowDescriptorCopy = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:[self.rowType copy] title:[self.title copy]];
rowDescriptorCopy.cellClass = [self.cellClass copy];
rowDescriptorCopy.cellConfig = [self.cellConfig mutableCopy];
rowDescriptorCopy.cellConfigAtConfigure = [self.cellConfigAtConfigure mutableCopy];
rowDescriptorCopy.disabled = self.isDisabled;
rowDescriptorCopy->_hidden = _hidden;
rowDescriptorCopy->_disabled = _disabled;
rowDescriptorCopy.required = self.isRequired;
rowDescriptorCopy.isDirtyDisablePredicateCache = YES;
rowDescriptorCopy.isDirtyHidePredicateCache = YES;
// =====================
// properties for Button
// =====================
rowDescriptorCopy.action = [self.action copy];
// ===========================
// property used for Selectors
@@ -170,6 +201,165 @@
return rowDescriptorCopy;
}
-(void)dealloc
{
[self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeDisabled];
[self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
@try {
[self removeObserver:self forKeyPath:@"value"];
}
@catch (NSException * __unused exception) {}
@try {
[self removeObserver:self forKeyPath:@"disablePredicateCache"];
}
@catch (NSException * __unused exception) {}
@try {
[self removeObserver:self forKeyPath:@"hidePredicateCache"];
}
@catch (NSException * __unused exception) {}
}
#pragma mark - KVO
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (!self.sectionDescriptor) return;
if (object == self && ([keyPath isEqualToString:@"value"] || [keyPath isEqualToString:@"hidePredicateCache"] || [keyPath isEqualToString:@"disablePredicateCache"])){
if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeSetting)]){
id newValue = [change objectForKey:NSKeyValueChangeNewKey];
id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
if ([keyPath isEqualToString:@"value"]){
[self.sectionDescriptor.formDescriptor.delegate formRowDescriptorValueHasChanged:object oldValue:oldValue newValue:newValue];
}
else{
[self.sectionDescriptor.formDescriptor.delegate formRowDescriptorPredicateHasChanged:object oldValue:oldValue newValue:newValue predicateType:([keyPath isEqualToString:@"hidePredicateCache"] ? XLPredicateTypeHidden : XLPredicateTypeDisabled)];
}
}
}
}
#pragma mark - Disable Predicate functions
-(BOOL)isDisabled
{
if (self.sectionDescriptor.formDescriptor.isDisabled){
return YES;
}
if (self.isDirtyDisablePredicateCache) {
[self evaluateIsDisabled];
}
return [self.disablePredicateCache boolValue];
}
-(void)setDisabled:(id)disabled
{
if ([_disabled isKindOfClass:[NSPredicate class]]){
[self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeDisabled];
}
_disabled = [disabled isKindOfClass:[NSString class]] ? [disabled formPredicate] : disabled;
if ([_disabled isKindOfClass:[NSPredicate class]]){
[self.sectionDescriptor.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeDisabled];
}
[self evaluateIsDisabled];
}
-(BOOL)evaluateIsDisabled
{
if ([_disabled isKindOfClass:[NSPredicate class]]) {
@try {
self.disablePredicateCache = @([_disabled evaluateWithObject:self substitutionVariables:self.sectionDescriptor.formDescriptor.allRowsByTag ?: @{}]);
}
@catch (NSException *exception) {
// predicate syntax error.
self.isDirtyDisablePredicateCache = YES;
};
}
else{
self.disablePredicateCache = _disabled;
}
return [self.disablePredicateCache boolValue];
}
-(id)disabled
{
return _disabled;
}
-(void)setDisablePredicateCache:(NSNumber*)disablePredicateCache
{
NSParameterAssert(disablePredicateCache);
self.isDirtyDisablePredicateCache = NO;
if (!_disablePredicateCache || ![_disablePredicateCache isEqualToNumber:disablePredicateCache]){
_disablePredicateCache = disablePredicateCache;
}
}
-(NSNumber*)disablePredicateCache
{
return _disablePredicateCache;
}
#pragma mark - Hide Predicate functions
-(NSNumber *)hidePredicateCache
{
return _hidePredicateCache;
}
-(void)setHidePredicateCache:(NSNumber *)hidePredicateCache
{
NSParameterAssert(hidePredicateCache);
self.isDirtyHidePredicateCache = NO;
if (!_hidePredicateCache || ![_hidePredicateCache isEqualToNumber:hidePredicateCache]){
_hidePredicateCache = hidePredicateCache;
}
}
-(BOOL)isHidden
{
if (self.isDirtyHidePredicateCache) {
return [self evaluateIsHidden];
}
return [self.hidePredicateCache boolValue];
}
-(BOOL)evaluateIsHidden
{
if ([_hidden isKindOfClass:[NSPredicate class]]) {
@try {
self.hidePredicateCache = @([_hidden evaluateWithObject:self substitutionVariables:self.sectionDescriptor.formDescriptor.allRowsByTag ?: @{}]);
}
@catch (NSException *exception) {
// predicate syntax error.
self.isDirtyHidePredicateCache = YES;
};
}
else{
self.hidePredicateCache = _hidden;
}
[self.hidePredicateCache boolValue] ? [self.sectionDescriptor hideFormRow:self] : [self.sectionDescriptor showFormRow:self];
return [self.hidePredicateCache boolValue];
}
-(void)setHidden:(id)hidden
{
if ([_hidden isKindOfClass:[NSPredicate class]]){
[self.sectionDescriptor.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
}
_hidden = [hidden isKindOfClass:[NSString class]] ? [hidden formPredicate] : hidden;
if ([_hidden isKindOfClass:[NSPredicate class]]){
[self.sectionDescriptor.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeHidden];
}
[self evaluateIsHidden]; // check and update if this row should be hidden.
}
-(id)hidden
{
return _hidden;
}
#pragma mark - validation
@@ -54,6 +54,8 @@ typedef NS_ENUM(NSUInteger, XLFormSectionInsertMode) {
@property (weak) XLFormDescriptor * formDescriptor;
@property id hidden;
-(BOOL)isHidden;
+(id)formSection;
+(id)formSectionWithTitle:(NSString *)title;
+197 -25
View File
@@ -25,24 +25,52 @@
#import "XLForm.h"
#import "XLFormSectionDescriptor.h"
#import "NSPredicate+XLFormAdditions.h"
#import "NSString+XLFormAdditions.h"
@interface XLFormDescriptor (_XLFormSectionDescriptor)
@property (readonly) NSDictionary* allRowsByTag;
-(void)addRowToTagCollection:(XLFormRowDescriptor*)rowDescriptor;
-(void)removeRowFromTagCollection:(XLFormRowDescriptor*) rowDescriptor;
-(void)showFormSection:(XLFormSectionDescriptor*)formSection;
-(void)hideFormSection:(XLFormSectionDescriptor*)formSection;
-(void)addObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
-(void)removeObserversOfObject:(id)sectionOrRow predicateType:(XLPredicateType)predicateType;
@end
@interface XLFormSectionDescriptor()
@property NSMutableArray * formRows;
@property NSMutableArray * allRows;
@property BOOL isDirtyHidePredicateCache;
@property (nonatomic) NSNumber* hidePredicateCache;
@end
@implementation XLFormSectionDescriptor
@synthesize hidden = _hidden;
@synthesize hidePredicateCache = _hidePredicateCache;
-(id)init
{
self = [super init];
if (self){
_formRows = [NSMutableArray array];
_allRows = [NSMutableArray array];
_sectionInsertMode = XLFormSectionInsertModeLastRow;
_sectionOptions = XLFormSectionOptionNone;
_title = nil;
_footerTitle = nil;
_hidden = @NO;
_hidePredicateCache = @NO;
_isDirtyHidePredicateCache = YES;
[self addObserver:self forKeyPath:@"formRows" options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:0];
}
return self;
}
@@ -59,6 +87,7 @@
[_multivaluedAddButton.cellConfig setObject:[UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0] forKey:@"textLabel.textColor"];
_multivaluedAddButton.action.formSelector = NSSelectorFromString(@"multivaluedInsertButtonTapped:");
[self insertObject:_multivaluedAddButton inFormRowsAtIndex:0];
[self insertObject:_multivaluedAddButton inAllRowsAtIndex:0];
}
}
return self;
@@ -96,35 +125,41 @@
-(void)addFormRow:(XLFormRowDescriptor *)formRow
{
[self insertObject:formRow inFormRowsAtIndex:([self canInsertUsingButton] ? [self.formRows count] - 1 : [self.formRows count])];
[self insertObject:formRow inAllRowsAtIndex:([self canInsertUsingButton] ? MAX(0, [self.formRows count] - 1) : [self.allRows count])];
}
-(void)addFormRow:(XLFormRowDescriptor *)formRow afterRow:(XLFormRowDescriptor *)afterRow
{
NSUInteger index;
if ((index = [self.formRows indexOfObject:afterRow]) != NSNotFound){
[self insertObject:formRow inFormRowsAtIndex:index + 1];
NSUInteger allRowIndex = [self.allRows indexOfObject:afterRow];
if (allRowIndex != NSNotFound) {
[self insertObject:formRow inAllRowsAtIndex:allRowIndex+1];
}
else {
else { //case when afterRow does not exist. Just insert at the end.
[self addFormRow:formRow];
return;
}
}
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)beforeRow
{
NSUInteger index;
if ((index = [self.formRows indexOfObject:beforeRow]) != NSNotFound){
[self insertObject:formRow inFormRowsAtIndex:index];
NSUInteger allRowIndex = [self.allRows indexOfObject:beforeRow];
if (allRowIndex != NSNotFound) {
[self insertObject:formRow inAllRowsAtIndex:allRowIndex];
}
else {
else { //case when afterRow does not exist. Just insert at the end.
[self addFormRow:formRow];
return;
}
}
-(void)removeFormRowAtIndex:(NSUInteger)index
{
if (self.formRows.count > index){
XLFormRowDescriptor *formRow = [self.formRows objectAtIndex:index];
NSUInteger allRowIndex = [self.allRows indexOfObject:formRow];
[self removeObjectFromFormRowsAtIndex:index];
[self removeObjectFromAllRowsAtIndex:allRowIndex];
}
}
@@ -133,25 +168,64 @@
NSUInteger index = NSNotFound;
if ((index = [self.formRows indexOfObject:formRow]) != NSNotFound){
[self removeFormRowAtIndex:index];
}
else if ((index = [self.allRows indexOfObject:formRow]) != NSNotFound){
if (self.allRows.count > index){
[self removeObjectFromAllRowsAtIndex:index];
}
};
}
- (void)moveRowAtIndexPath:(NSIndexPath *)sourceIndex toIndexPath:(NSIndexPath *)destinationIndex
{
if ((sourceIndex.row < self.formRows.count) && (destinationIndex.row < self.formRows.count)){
if ((sourceIndex.row < self.formRows.count) && (destinationIndex.row < self.formRows.count) && (sourceIndex.row != destinationIndex.row)){
XLFormRowDescriptor * row = [self objectInFormRowsAtIndex:sourceIndex.row];
XLFormRowDescriptor * destRow = [self objectInFormRowsAtIndex:destinationIndex.row];
[self.formRows removeObjectAtIndex:sourceIndex.row];
[self.formRows insertObject:row atIndex:destinationIndex.row];
[self.allRows removeObjectAtIndex:[self.allRows indexOfObject:row]];
[self.allRows insertObject:row atIndex:[self.allRows indexOfObject:destRow]];
}
}
-(void)dealloc
{
for (XLFormRowDescriptor * formRow in self.formRows) {
@try {
[formRow removeObserver:self forKeyPath:@"value"];
[self.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
@try {
[self removeObserver:self forKeyPath:@"formRows"];
}
@catch (NSException * __unused exception) {}
}
#pragma mark - Show/hide rows
-(void)showFormRow:(XLFormRowDescriptor*)formRow{
NSUInteger formIndex = [self.formRows indexOfObject:formRow];
if (formIndex != NSNotFound) {
return;
}
NSUInteger index = [self.allRows indexOfObject:formRow];
if (index != NSNotFound){
while (formIndex == NSNotFound && index > 0) {
XLFormRowDescriptor* previous = [self.allRows objectAtIndex:--index];
formIndex = [self.formRows indexOfObject:previous];
}
@catch (NSException * __unused exception) {}
if (formIndex == NSNotFound){ // index == 0 => insert at the beginning
[self insertObject:formRow inFormRowsAtIndex:0];
}
else {
[self insertObject:formRow inFormRowsAtIndex:formIndex+1];
}
}
}
-(void)hideFormRow:(XLFormRowDescriptor*)formRow{
NSUInteger index = [self.formRows indexOfObject:formRow];
if (index != NSNotFound){
[self removeObjectFromFormRowsAtIndex:index];
}
}
@@ -159,11 +233,21 @@
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if ([object isKindOfClass:[XLFormRowDescriptor class]] && [keyPath isEqualToString:@"value"]){
if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeSetting)]){
id newValue = [change objectForKey:NSKeyValueChangeNewKey];
id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
[self.formDescriptor.delegate formRowDescriptorValueHasChanged:object oldValue:oldValue newValue:newValue];
if (!self.formDescriptor.delegate) return;
if ([keyPath isEqualToString:@"formRows"]){
if ([self.formDescriptor.formSections containsObject:self]){
if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeInsertion)]){
NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
XLFormRowDescriptor * formRow = [((XLFormSectionDescriptor *)object).formRows objectAtIndex:indexSet.firstIndex];
NSUInteger sectionIndex = [self.formDescriptor.formSections indexOfObject:object];
[self.formDescriptor.delegate formRowHasBeenAdded:formRow atIndexPath:[NSIndexPath indexPathForRow:indexSet.firstIndex inSection:sectionIndex]];
}
else if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeRemoval)]){
NSIndexSet * indexSet = [change objectForKey:NSKeyValueChangeIndexesKey];
XLFormRowDescriptor * removedRow = [[change objectForKey:NSKeyValueChangeOldKey] objectAtIndex:0];
NSUInteger sectionIndex = [self.formDescriptor.formSections indexOfObject:object];
[self.formDescriptor.delegate formRowHasBeenRemoved:removedRow atIndexPath:[NSIndexPath indexPathForRow:indexSet.firstIndex inSection:sectionIndex]];
}
}
}
}
@@ -190,20 +274,48 @@
- (void)insertObject:(XLFormRowDescriptor *)formRow inFormRowsAtIndex:(NSUInteger)index
{
formRow.sectionDescriptor = self;
[formRow addObserver:self forKeyPath:@"value" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
[self.formRows insertObject:formRow atIndex:index];
}
- (void)removeObjectFromFormRowsAtIndex:(NSUInteger)index
{
XLFormRowDescriptor * formRow = [self.formRows objectAtIndex:index];
@try {
[formRow removeObserver:self forKeyPath:@"value"];
}
@catch (NSException * __unused exception) {}
[self.formRows removeObjectAtIndex:index];
}
#pragma mark - KVC ALL
-(NSUInteger)countOfAllRows
{
return self.allRows.count;
}
- (id)objectInAllRowsAtIndex:(NSUInteger)index
{
return [self.allRows objectAtIndex:index];
}
- (NSArray *)allRowsAtIndexes:(NSIndexSet *)indexes
{
return [self.allRows objectsAtIndexes:indexes];
}
- (void)insertObject:(XLFormRowDescriptor *)row inAllRowsAtIndex:(NSUInteger)index
{
row.sectionDescriptor = self;
[self.formDescriptor addRowToTagCollection:row];
[self.allRows insertObject:row atIndex:index];
row.disabled = row.disabled;
row.hidden = row.hidden;
}
- (void)removeObjectFromAllRowsAtIndex:(NSUInteger)index
{
XLFormRowDescriptor * row = [self.allRows objectAtIndex:index];
[self.formDescriptor removeRowFromTagCollection:row];
[self.formDescriptor removeObserversOfObject:row predicateType:XLPredicateTypeDisabled];
[self.formDescriptor removeObserversOfObject:row predicateType:XLPredicateTypeHidden];
[self.allRows removeObjectAtIndex:index];
}
#pragma mark - Helpers
@@ -212,5 +324,65 @@
return (self.sectionInsertMode == XLFormSectionInsertModeButton && self.sectionOptions & XLFormSectionOptionCanInsert);
}
#pragma mark - Predicates
-(NSNumber *)hidePredicateCache
{
return _hidePredicateCache;
}
-(void)setHidePredicateCache:(NSNumber *)hidePredicateCache
{
NSParameterAssert(hidePredicateCache);
self.isDirtyHidePredicateCache = NO;
if (!_hidePredicateCache || ![_hidePredicateCache isEqualToNumber:hidePredicateCache]){
_hidePredicateCache = hidePredicateCache;
}
}
-(BOOL)isHidden
{
if (self.isDirtyHidePredicateCache) {
return [self evaluateIsHidden];
}
return self.hidePredicateCache;
}
-(BOOL)evaluateIsHidden
{
if ([_hidden isKindOfClass:[NSPredicate class]]) {
@try {
self.hidePredicateCache = @([_hidden evaluateWithObject:self substitutionVariables:self.formDescriptor.allRowsByTag ?: @{}]);
}
@catch (NSException *exception) {
// predicate syntax error.
self.isDirtyHidePredicateCache = YES;
};
}
else{
self.hidePredicateCache = _hidden;
}
[self.hidePredicateCache boolValue] ? [self.formDescriptor hideFormSection:self] : [self.formDescriptor showFormSection:self] ;
return [self.hidePredicateCache boolValue];
}
-(id)hidden
{
return _hidden;
}
-(void)setHidden:(id)hidden
{
if ([_hidden isKindOfClass:[NSPredicate class]]){
[self.formDescriptor removeObserversOfObject:self predicateType:XLPredicateTypeHidden];
}
_hidden = [hidden isKindOfClass:[NSString class]] ? [hidden formPredicate] : hidden;
if ([_hidden isKindOfClass:[NSPredicate class]]){
[self.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeHidden];
}
[self evaluateIsHidden]; // check and update if this row should be hidden.
}
@end
@@ -0,0 +1,33 @@
//
// NSExpression+XLFormAdditions.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 <Foundation/Foundation.h>
@interface NSExpression (XLFormAdditions)
-(NSMutableArray*) getExpressionVars;
@end
@@ -0,0 +1,50 @@
//
// NSExpression+XLFormAdditions.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "NSExpression+XLFormAdditions.h"
@implementation NSExpression (XLFormAdditions)
-(NSMutableArray*) getExpressionVars{
switch (self.expressionType) {
case NSFunctionExpressionType:{
NSString* str = [NSString stringWithFormat:@"%@", self];
if ([str containsString:@"."])
str = [str substringWithRange:NSMakeRange(1, [str rangeOfString:@"."].location - 1)];
else
str = [str substringFromIndex:1];
return [[NSMutableArray alloc] initWithObjects: str, nil];
break;
}
default:
return nil;
break;
}
}
@end
@@ -0,0 +1,31 @@
//
// NSPredicate+XLFormAdditions.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 <Foundation/Foundation.h>
@interface NSPredicate (XLFormAdditions)
-(NSMutableArray*) getPredicateVars;
@end
@@ -0,0 +1,45 @@
//
// NSPredicate+XLFormAdditions.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "NSPredicate+XLFormAdditions.h"
#import "NSExpression+XLFormAdditions.h"
@implementation NSPredicate (XLFormAdditions)
-(NSMutableArray*) getPredicateVars{
NSMutableArray* ret = [[NSMutableArray alloc] init];
if ([self isKindOfClass:([NSCompoundPredicate class])]) {
for (id object in ((NSCompoundPredicate*) self).subpredicates ) {
[ret addObjectsFromArray:[object getPredicateVars]];
}
}
else if ([self isKindOfClass:([NSComparisonPredicate class])]){
[ret addObjectsFromArray:[((NSComparisonPredicate*) self).leftExpression getExpressionVars]];
[ret addObjectsFromArray:[((NSComparisonPredicate*) self).rightExpression getExpressionVars]];
}
return ret;
}
@end
@@ -0,0 +1,35 @@
//
// NSString+XLFormAdditions.h
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 <Foundation/Foundation.h>
#import "XLFormDescriptor.h"
@interface NSString (XLFormAdditions)
-(NSPredicate *)formPredicate;
-(NSString *)formKeyForPredicateType:(XLPredicateType)predicateType;
@end
@@ -0,0 +1,65 @@
//
// NSString+XLFormAdditions.m
// XLForm ( https://github.com/xmartlabs/XLForm )
//
// Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
//
//
// 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 "NSString+XLFormAdditions.h"
@implementation NSString (XLFormAdditions)
-(NSPredicate *)formPredicate
{
// returns an array of strings where the first one is the new string with the correct replacements
// and the rest are all the tags that appear in the string
NSString* separator = @"$";
NSArray* tokens = [self componentsSeparatedByString:separator];
NSMutableString* new_string = [[NSMutableString alloc] initWithString:tokens[0]];
NSRange range;
for (int i = 1; i < tokens.count; i++) {
[new_string appendString:separator];
NSArray* subtokens = [[tokens[i] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" <>!=+-&|"]][0]
componentsSeparatedByString:@"."];
NSString* tag = subtokens[0];
NSString* attribute;
if ([subtokens count] >= 2) {
attribute = subtokens[1];
}
[new_string appendString:tag];
range = [tokens[i] rangeOfString:[NSString stringWithFormat:@"%@", tag]];
if (!attribute || (![attribute isEqualToString:@"value"] && ![attribute isEqualToString:@"isHidden"] && ![attribute isEqualToString:@"isDisabled"])){
[new_string appendString:@".value"];
}
[new_string appendString:[tokens[i] substringFromIndex:range.location + range.length]];
}
return [NSPredicate predicateWithFormat:new_string];
}
-(NSString *)formKeyForPredicateType:(XLPredicateType)predicateType
{
return [NSString stringWithFormat:@"%@-%@", self, (predicateType == XLPredicateTypeHidden ? @"hidden" : @"disabled") ];
}
@end
+2
View File
@@ -92,9 +92,11 @@ extern NSString *const XLFormRowDescriptorTypeSelectorSegmentedControl;
extern NSString *const XLFormRowDescriptorTypeDateInline;
extern NSString *const XLFormRowDescriptorTypeDateTimeInline;
extern NSString *const XLFormRowDescriptorTypeTimeInline;
extern NSString *const XLFormRowDescriptorTypeCountDownTimerInline;
extern NSString *const XLFormRowDescriptorTypeDate;
extern NSString *const XLFormRowDescriptorTypeDateTime;
extern NSString *const XLFormRowDescriptorTypeTime;
extern NSString *const XLFormRowDescriptorTypeCountDownTimer;
extern NSString *const XLFormRowDescriptorTypeDatePicker;
extern NSString *const XLFormRowDescriptorTypePicker;
extern NSString *const XLFormRowDescriptorTypeSlider;
+2
View File
@@ -51,9 +51,11 @@ NSString *const XLFormRowDescriptorTypeSelectorSegmentedControl = @"selectorSegm
NSString *const XLFormRowDescriptorTypeDateInline = @"dateInline";
NSString *const XLFormRowDescriptorTypeDateTimeInline = @"datetimeInline";
NSString *const XLFormRowDescriptorTypeTimeInline = @"timeInline";
NSString *const XLFormRowDescriptorTypeCountDownTimerInline = @"countDownTimerInline";
NSString *const XLFormRowDescriptorTypeDate = @"date";
NSString *const XLFormRowDescriptorTypeDateTime = @"datetime";
NSString *const XLFormRowDescriptorTypeTime = @"time";
NSString *const XLFormRowDescriptorTypeCountDownTimer = @"countDownTimer";
NSString *const XLFormRowDescriptorTypeDatePicker = @"datePicker";
NSString *const XLFormRowDescriptorTypePicker = @"picker";
NSString *const XLFormRowDescriptorTypeSlider = @"slider";