81 Commits

Author SHA1 Message Date
Martin Barreto 1738fb8e35 update version 2015-08-17 21:36:11 -03:00
Mathias Claassen c3be940cc4 updated readme for cell configuration 2015-08-17 14:44:01 -03:00
Mathias Claassen dddbb74e95 Readme FAQ update 2015-08-17 14:01:51 -03:00
mats-claassen ef90f35a0f Merge pull request #505 from xmartlabs/fix/issue485
Fix/issue485
2015-08-14 17:51:47 -03:00
Mathias Claassen c03878e656 Merge branch 'master' into fix/issue485 2015-08-14 17:51:05 -03:00
Mathias Claassen 853254d75e Updated inline picker scrolling algorithm
closes #485
2015-08-14 17:50:30 -03:00
mats-claassen 460b116018 Merge pull request #504 from xmartlabs/fix/issue497
Fixed selector push value update bug.
2015-08-14 12:43:30 -03:00
Mathias Claassen 6a501e21fb Fixed selector push value update bug.
closes #497
2015-08-14 12:41:40 -03:00
Martin Barreto 6725d0a9b4 call setNeedsUpdateConstraints to make sure updateConstraints method is called. fix #486 2015-08-02 17:01:26 -03:00
Martin Barreto daaf720c29 fix #484 2015-08-01 21:21:59 -03:00
Martin Barreto bcd9ef118e Merge pull request #482 from Cee/master
Fix a typo
2015-08-01 17:32:34 -03:00
Cee cb9d40ba3a Fix a typo 2015-08-01 23:48:27 +08:00
Martin Barreto afcf2071ed Merge pull request #481 from xmartlabs/fix/issue465
Fix/issue465
2015-07-31 21:29:57 -03:00
Mathias Claassen 12b7012a1b Updated fix. Added CountDownTimer to inline row list 2015-07-31 12:20:02 -03:00
Mathias Claassen 8632b5bb42 Fixed issue #465 2015-07-30 10:55:02 -03:00
Martin Barreto ff2d869ee0 Merge pull request #474 from xmartlabs/feature/newpod
new pod version v3.0.1
2015-07-29 15:37:15 -03:00
Martin Barreto 486595922f new pod versin v3.0.1 2015-07-29 15:37:49 -03:00
Martin Barreto 9138c413f1 Merge pull request #473 from xmartlabs/fix/issue393
Fix issue #393
2015-07-28 21:03:02 -03:00
Martin Barreto 96c0999bf7 Merge pull request #470 from xmartlabs/issue#325
Issue #325 fix
2015-07-28 21:00:47 -03:00
Martin Barreto 79c14e3346 Use the metadata to know which are the inline rows. 2015-07-28 20:57:55 -03:00
Martin Barreto a28b595abd Merge pull request #471 from xmartlabs/fix/predicateparsing
Added "()" characters to separators when parsing strings to form pred…
2015-07-28 20:29:42 -03:00
Mathias Claassen 9de19aa0d8 Fix issue #393 2015-07-28 15:28:50 -03:00
Martin Pastorin d2a99cf8ce Merge pull request #472 from xmartlabs/issue#168
issue #168 - set row's textfield length
2015-07-28 14:37:33 -03:00
pastorin 029d88a901 issue #168 - set row's textfield length 2015-07-28 14:33:15 -03:00
Mathias Claassen d454cc284d Added "()" characters to separators when parsing strings to form predicates 2015-07-28 11:49:11 -03:00
pastorin 612807d9c3 Issue #325 fix
Accessory view should not be displayed on Inline date pickers
2015-07-28 11:21:47 -03:00
Martin Barreto c8ebb733ce fix #434 2015-07-28 00:08:14 -03:00
Martin Barreto 175f10397b Merge pull request #467 from stevemoser/patch-1
Remove setting the root VC in init
2015-07-27 22:48:18 -03:00
mats-claassen 094715028c Merge pull request #469 from xmartlabs/fix/hiddenAndDisabledRows
on change block
2015-07-27 15:43:54 -03:00
Mathias Claassen 169f9f9778 Modified onChangeBlock to send rowDescriptor 2015-07-27 15:39:34 -03:00
Mathias Claassen 9bc80c6c0d on change block 2015-07-27 13:55:25 -03:00
Martin Barreto ecc9ec45fb Merge pull request #466 from xmartlabs/issue#460
issue #460 fix
2015-07-27 13:15:59 -03:00
mats-claassen d479a91f47 Merge pull request #468 from xmartlabs/fix/hiddenAndDisabledRows
Hidden and disabled rows resign first responder before changing state
2015-07-27 12:42:25 -03:00
Mathias Claassen 014030a99e Hidden and disabled rows resign first responder before changing state 2015-07-27 12:38:24 -03:00
Steve Moser deb34b01b0 Remove setting the root VC in init
For the event example it is already set in the storyboard so it is not needed here.
2015-07-27 11:15:14 -04:00
pastorin 79d9412ea3 issue #460 fix 2015-07-27 11:04:49 -03:00
Martin Barreto a2feb45ad7 Merge pull request #462 from AlexZd/master
[PATCH] Allow Developers to use XLForm in their Frameworks
2015-07-27 00:21:06 -03:00
Martin Barreto bea7afcb60 Merge pull request #458 from xmartlabs/AlertController
iOS8 and above - Replace UIAlertView and UIActionSheet for UIAlertController
2015-07-25 01:02:26 -03:00
Martin Barreto 1854bd49a4 minor fix. 2015-07-25 00:58:12 -03:00
Martin Barreto bb1d4bedc8 Use new Alert/Style controller class when possible. 2015-07-25 00:39:11 -03:00
Martin Barreto ebf4915899 fix doc typo 2015-07-24 16:24:00 -03:00
pastorin 22c8f06d43 iOS8 and above - Replace UIAlertView and UIActionSheet for UIAlertController 2015-07-24 15:13:53 -03:00
Martin Barreto 47aa759602 Merge pull request #455 from xmartlabs/StepCounterChanges
Improve StepCounter
2015-07-23 15:35:03 -03:00
pastorin da241efcc0 - Add StepCounter documentation
- Add StepCounter custom values example
- Fix XLFormStepCounterCell bug
2015-07-23 15:33:38 -03:00
Martin Barreto 09176bff39 Merge pull request #454 from xmartlabs/issue#398
issue #398 fix
2015-07-23 13:05:22 -03:00
Martin Barreto d3fc9b2093 Merge pull request #453 from xmartlabs/issue#386
issue #386 fix
2015-07-23 12:45:37 -03:00
pastorin 8c9351cd12 issue #398 fix 2015-07-23 12:37:26 -03:00
pastorin 560aec29c6 issue #386 fix 2015-07-23 11:27:18 -03:00
Martin Barreto 941f8fcfc3 Merge pull request #449 from xmartlabs/fix/TextFieldLayouts
Fix/text field layouts
2015-07-22 17:23:07 -03:00
pastorin 65c5431761 issue #409 fix 2015-07-22 17:18:34 -03:00
pastorin 1c1c95408f Merge branch 'master' of https://github.com/xmartlabs/XLForm into fix/TextFieldLayouts 2015-07-22 17:08:03 -03:00
Martin Pastorin cda07b2a64 Merge pull request #448 from xmartlabs/issue#429Constraints
issue #429 fix
2015-07-22 15:54:31 -03:00
pastorin 6fac42b190 issue #429 fix 2015-07-22 15:42:43 -03:00
Martin Barreto 4a641c4a7c Merge pull request #444 from openhood/keep-valueTransformer-on-copy
Ensure XLFormRowDescriptor valueTransform is kept on copy
2015-07-22 13:47:45 -03:00
Jonathan Tron a36ae6d90a Ensure XLFormRowDescriptor valueTransform is kept on copy 2015-07-22 17:38:16 +02:00
Martin Barreto 60657c0cf8 Merge pull request #441 from tommypeps/fixed#422
email long
2015-07-21 20:20:09 -03:00
Martin Barreto a114e9bda5 Merge pull request #440 from iOSCowboy/patch-1
Define 'DSL' in README file
2015-07-21 20:17:22 -03:00
Hector Zarate 4113135298 Define 'DSL' in README file 2015-07-21 22:55:12 +02:00
tommypeps 9503cbe8ed email long 2015-07-21 22:50:54 +02:00
Martin Barreto 36fa5e7071 Update README.md 2015-07-21 00:27:30 -03:00
Martin Barreto 6566ef81f8 Merge pull request #438 from xmartlabs/feature/swift1_2
Xcode 6.2 & swift1.2 support
2015-07-20 23:39:46 -03:00
Martin Barreto f019da0edc build version update. 2015-07-20 23:30:29 -03:00
Martin Barreto 20ca33e2e8 swift fixes. 2015-07-20 22:50:13 -03:00
mikeEllis 31f2fce646 swift 1.2 fixes 2015-07-20 17:19:00 -03:00
Martin Barreto 39280687e8 Merge pull request #432 from santiagofm/replace-xldataloader-with-xldata
replace xldataloader in objc examples with xldata
2015-07-17 16:52:41 -03:00
Santiago Fernandez 76b9d85154 update to xldata 2.0.0 2015-07-17 16:31:04 -03:00
Santiago Fernandez e6661b6526 replace xldataloader in objc examples with xldata 2015-07-16 10:58:02 -03:00
Martin Barreto 6e4574836b Merge branch 'master' of github.com:xmartlabs/XLForm 2015-07-15 01:25:29 -03:00
Martin Barreto 3822ed74e5 reload form whenever self.form is assigned. 2015-07-15 01:25:18 -03:00
Martin Barreto 49a2fb8f96 Merge pull request #425 from kevindeleon/patch-1
Fixes spelling error in requested change.
2015-07-14 12:55:35 -03:00
Martin Barreto 7929580f5d Merge pull request #427 from kevindeleon/patch-3
Figured these same spelling errors were here as well
2015-07-14 12:53:28 -03:00
Martin Barreto 03d8b0a35c Merge pull request #426 from kevindeleon/patch-2
fixes a few more spelling errors.
2015-07-14 12:53:07 -03:00
Kevin deLeon 7bbfab3c6b fixes a spelling error I missed. 2015-07-14 08:58:07 -05:00
Kevin deLeon 84a2f55609 Figured these same spelling errors were here as well 2015-07-14 08:55:36 -05:00
Kevin deLeon 8273745356 fixes a few more spelling errors. 2015-07-14 08:52:38 -05:00
Kevin deLeon 2e3e267bfe Fixes spelling error in requested change. 2015-07-14 08:50:01 -05:00
Martin Barreto 4c68391763 Update README.md 2015-07-10 22:34:06 -03:00
Sebastian Vogelsang 94f22d9b54 made textFields within XLFormTextFieldCells a min. width of 1/3 screen width. That way very long labels cannot squeeze the textField until input becomes impossible. Also labels are multi-line now. 2015-07-09 15:15:10 +02:00
Martin Barreto d94b027c17 minor example project fix. row tag (key) was wrong. 2015-06-20 11:24:00 -03:00
Martin Barreto 549a6be69f #389 2015-06-19 11:33:54 -03:00
AlexZd 3a71cfe6e2 [PATCH] Allow Developers to use XLForm in their Frameworks 2015-06-11 17:37:57 +04:00
70 changed files with 1050 additions and 1216 deletions
+1
View File
@@ -1,4 +1,5 @@
language: objective-c
osx_image: xcode6.4
before_install:
- gem install cocoapods --no-rdoc --no-ri --no-document --quiet
- gem install xcpretty --no-rdoc --no-ri --no-document --quiet
@@ -169,7 +169,7 @@ NSString * kAccessoryViewNotes = @"notes";
[row.cellConfigAtConfigure setObject:@"TEXT VIEW EXAMPLE" forKey:@"textView.placeholder"];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Ckeck"];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Check"];
[section addFormRow:row];
section = [XLFormSectionDescriptor formSection];
@@ -23,7 +23,6 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import "CoreDataStore.h"
#import "ExamplesFormViewController.h"
#import "AppDelegate.h"
@@ -75,8 +75,7 @@ NSString *const kCountDownTimer = @"countDownTimer";
dateComp.hour = 0;
dateComp.minute = 7;
dateComp.timeZone = [NSTimeZone systemTimeZone];
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
row.value = [calendar dateFromComponents:dateComp];
[section addFormRow:row];
@@ -158,13 +157,32 @@ NSString *const kCountDownTimer = @"countDownTimer";
[super formRowDescriptorValueHasChanged:formRow oldValue:oldValue newValue:newValue];
if([formRow.tag isEqualToString:kDatePicker])
{
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"DatePicker"
message:@"Value Has changed!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message show];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"DatePicker"
message:@"Value Has changed!"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:@"DatePicker"
message:@"Value Has changed!"
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[message show];
}
#endif
}
}
@@ -129,8 +129,34 @@ NSString *const kNotes = @"notes";
return;
}
[self.tableView endEditing:YES];
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Valid Form", nil) message:@"No errors found" delegate:self cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil];
[alertView show];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Valid Form", nil)
message:@"No errors found"
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
#else
if ([UIAlertController class]){
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Valid Form", nil)
message:@"No errors found"
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Valid Form", nil)
message:@"No errors found"
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
}
#endif
}
@end
@@ -85,11 +85,67 @@
-(void)addDidTouch:(UIBarButtonItem * __unused)sender
{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"Cancel" destructiveButtonTitle:@"Remove Last Section" otherButtonTitles:@"Add a section at the end", self.form.isDisabled ? @"Enable Form" : @"Disable Form", nil];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Remove Last Section"
otherButtonTitles:@"Add a section at the end", self.form.isDisabled ? @"Enable Form" : @"Disable Form", nil];
[actionSheet showInView:self.view];
#else
if ([UIAlertController class]){
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:nil
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
__weak __typeof(self)weakSelf = self;
[alertController addAction:[UIAlertAction actionWithTitle:@"Remove Last Section"
style:UIAlertActionStyleDestructive
handler:^(UIAlertAction *action) {
if (weakSelf.form.formSections.count > 0){
// remove last section
[weakSelf.form removeFormSectionAtIndex:(weakSelf.form.formSections.count - 1)];
}
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Add a section at the end"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
// add a new section
XLFormSectionDescriptor * newSection = [XLFormSectionDescriptor formSectionWithTitle:[NSString stringWithFormat:@"Section created at %@", [NSDateFormatter localizedStringFromDate:[NSDate new] dateStyle:NSDateFormatterShortStyle timeStyle:NSDateFormatterShortStyle]] sectionOptions:XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete];
newSection.multivaluedTag = [NSString stringWithFormat:@"multivaluedPushSelector_%@", @(weakSelf.form.formSections.count)];
XLFormRowDescriptor * newRow = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorPush title:@"Tap to select ;).."];
newRow.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3"];
[newSection addFormRow:newRow];
[weakSelf.form addFormSection:newSection];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:self.form.isDisabled ? @"Enable Form" : @"Disable Form"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
weakSelf.form.disabled = !weakSelf.form.disabled;
[weakSelf.tableView endEditing:YES];
[weakSelf.tableView reloadData];
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Remove Last Section"
otherButtonTitles:@"Add a section at the end", self.form.isDisabled ? @"Enable Form" : @"Disable Form", nil];
[actionSheet showInView:self.view];
}
#endif
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
@@ -109,13 +165,15 @@
[newSection addFormRow:newRow];
[self.form addFormSection:newSection];
}
else {
else if (![[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Cancel"]){
self.form.disabled = !self.form.disabled;
[self.tableView endEditing:YES];
[self.tableView reloadData];
}
}
#endif
@end
@@ -92,12 +92,57 @@ NSString *const kFormImageSelectorCellImageRequest = @"imageRequest";
-(void)formDescriptorCellDidSelectedWithFormController:(XLFormViewController *)controller
{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle delegate:self
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
destructiveButtonTitle:nil
otherButtonTitles:NSLocalizedString(@"XLFormImageSelectorCell_ChooseExistingPhoto", @"Choose Existing Photo"), NSLocalizedString(@"XLFormImageSelectorCell_TakePicture", @"Take a Picture"), nil];
actionSheet.tag = self.tag;
[actionSheet showInView:self.formViewController.view];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:self.rowDescriptor.selectorTitle
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
__weak __typeof(self)weakSelf = self;
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"XLFormImageSelectorCell_ChooseExistingPhoto", @"Choose Existing Photo")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = weakSelf;
imagePickerController.allowsEditing = YES;
imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
[weakSelf.formViewController presentViewController:imagePickerController animated:YES completion:nil];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"XLFormImageSelectorCell_TakePicture", @"Take a Picture")
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = weakSelf;
imagePickerController.allowsEditing = YES;
imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
[weakSelf.formViewController presentViewController:imagePickerController animated:YES completion:nil];
}]];
[self.formViewController presentViewController:alertController animated:YES completion:nil];
}
else{
UIActionSheet *actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self
cancelButtonTitle:NSLocalizedString(@"Cancel", nil)
destructiveButtonTitle:nil
otherButtonTitles:NSLocalizedString(@"XLFormImageSelectorCell_ChooseExistingPhoto", @"Choose Existing Photo"), NSLocalizedString(@"XLFormImageSelectorCell_TakePicture", @"Take a Picture"), nil];
actionSheet.tag = self.tag;
[actionSheet showInView:self.formViewController.view];
}
#endif
}
#pragma mark - LayoutConstraints
@@ -168,9 +213,14 @@ NSString *const kFormImageSelectorCellImageRequest = @"imageRequest";
[self.textLabel removeObserver:self forKeyPath:@"text"];
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
- (void)actionSheet:(UIActionSheet * __unused)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
imagePickerController.delegate = self;
@@ -187,6 +237,8 @@ NSString *const kFormImageSelectorCellImageRequest = @"imageRequest";
}
}
#endif
#pragma mark - UIImagePickerControllerDelegate
- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
@@ -27,7 +27,7 @@
#import "OthersFormViewController.h"
NSString *const kSwitchBool = @"switchBool";
NSString *const kSwitchCheck = @"switchBool";
NSString *const kSwitchCheck = @"switchCheck";
NSString *const kStepCounter = @"stepCounter";
NSString *const kSlider = @"slider";
NSString *const kSegmentedControl = @"segmentedControl";
@@ -44,7 +44,7 @@ NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
@implementation OthersFormViewController
- (instancetype)initWithCoder:(NSCoder *)coder
-(instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithCoder:coder];
if (self) {
@@ -53,7 +53,7 @@ NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
return self;
}
- (id)init
-(instancetype)init
{
self = [super init];
if (self){
@@ -79,10 +79,16 @@ NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
[section addFormRow:[XLFormRowDescriptor formRowDescriptorWithTag:kSwitchCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Check"]];
// step counter
[section addFormRow:[XLFormRowDescriptor formRowDescriptorWithTag:kStepCounter rowType:XLFormRowDescriptorTypeStepCounter title:@"Step counter"]];
XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:kStepCounter rowType:XLFormRowDescriptorTypeStepCounter title:@"Step counter"];
row.value = @50;
[row.cellConfigAtConfigure setObject:@YES forKey:@"stepControl.wraps"];
[row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.stepValue"];
[row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.minimumValue"];
[row.cellConfigAtConfigure setObject:@100 forKey:@"stepControl.maximumValue"];
[section addFormRow:row];
// Segmented Control
XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:kSegmentedControl rowType:XLFormRowDescriptorTypeSelectorSegmentedControl title:@"Fruits"];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSegmentedControl rowType:XLFormRowDescriptorTypeSelectorSegmentedControl title:@"Fruits"];
row.selectorOptions = @[@"Apple", @"Orange", @"Pear"];
row.value = @"Pear";
[section addFormRow:row];
@@ -110,22 +116,44 @@ NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
// Button
XLFormRowDescriptor * buttonRow = [XLFormRowDescriptor formRowDescriptorWithTag:kButton rowType:XLFormRowDescriptorTypeButton title:@"Button"];
[buttonRow.cellConfig setObject:[UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0] forKey:@"textLabel.textColor"];
buttonRow.action.formSelector = @selector(didTouchButton:);
[section addFormRow:buttonRow];
// Left Button
XLFormRowDescriptor * buttonLeftAlignedRow = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonLeftAligned rowType:XLFormRowDescriptorTypeButton title:@"Button with Block"];
[buttonLeftAlignedRow.cellConfig setObject:[UIColor colorWithRed:0.0 green:122.0/255.0 blue:1.0 alpha:1.0] forKey:@"textLabel.textColor"];
[buttonLeftAlignedRow.cellConfig setObject:@(NSTextAlignmentLeft) forKey:@"textLabel.textAlignment"];
[buttonLeftAlignedRow.cellConfig setObject:@(UITableViewCellAccessoryDisclosureIndicator) forKey:@"accessoryType"];
__typeof(self) __weak weakSelf = self;
buttonLeftAlignedRow.action.formBlock = ^(XLFormRowDescriptor * sender){
if ([[sender.sectionDescriptor.formDescriptor formRowWithTag:kSwitchBool].value boolValue]){
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil) message:@"Button has checked the switch value..." delegate:weakSelf cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil];
[alertView show];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
delegate:weakSelf
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
delegate:weakSelf
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
}
#endif
}
[weakSelf deselectFormRow:sender];
};
@@ -162,8 +190,33 @@ NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
-(void)didTouchButton:(XLFormRowDescriptor *)sender
{
if ([[sender.sectionDescriptor.formDescriptor formRowWithTag:kSwitchBool].value boolValue]){
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil) message:@"Button has checked the switch value..." delegate:self cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil];
[alertView show];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
delegate:self
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"OK", nil)
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView *message = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Switch is ON", nil)
message:@"Button has checked the switch value..."
delegate:self
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[message show];
}
#endif
}
[self deselectFormRow:sender];
}
@@ -103,11 +103,14 @@ NSString *const kPredDep2 = @"preddep2";
[section addFormRow:row];
row.hidden = [NSString stringWithFormat:@"$%@.isDisabled == 1 AND $%@.value contains[c] 'Out'", pred4, pred];
typeof(self) __weak weakself = self;
row.onChangeBlock = ^(id oldValue, id newValue, XLFormRowDescriptor* __unused rowDescriptor){
UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"Account Field changed" message:[NSString stringWithFormat:@"Old value: %@\nNew value: %@", oldValue, newValue ] preferredStyle:UIAlertControllerStyleActionSheet];
[alert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
[weakself.navigationController presentViewController:alert animated:YES completion:nil];
};
self.form = form;
}
@end
@@ -30,12 +30,6 @@
@implementation NativeEventNavigationViewController
-(id)init
{
self = [super initWithRootViewController:[[NativeEventFormViewController alloc] init]];
return self;
}
-(void)viewDidLoad
{
[super viewDidLoad];
@@ -29,8 +29,31 @@
NSString *const kSelectorUser = @"selectorUser";
NSString *const kSelectorUserPopover = @"kSelectorUserPopover";
@implementation DynamicSelectorsFormViewController
@interface UserTransformer : NSValueTransformer
@end
@implementation UserTransformer
+ (Class)transformedValueClass
{
return [NSString class];
}
+ (BOOL)allowsReverseTransformation
{
return NO;
}
- (id)transformedValue:(id)value
{
if (!value) return nil;
NSDictionary *user = (NSDictionary *) value;
return [user valueForKeyPath:@"user.name"];
}
@end
@implementation DynamicSelectorsFormViewController
-(id)init
{
@@ -48,19 +71,24 @@ NSString *const kSelectorUserPopover = @"kSelectorUserPopover";
// Selector Push
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorUser rowType:XLFormRowDescriptorTypeSelectorPush title:@"User"];
row.action.viewControllerClass = [UsersTableViewController class];
row.action.viewControllerStoryboardId = @"UsersTableViewController";
row.valueTransformer = [UserTransformer class];
[section addFormRow:row];
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
// Selector PopOver
row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorUserPopover rowType:XLFormRowDescriptorTypeSelectorPopover title:@"User Popover"];
row.action.viewControllerClass = [UsersTableViewController class];
[section addFormRow:row];
}
// if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
// // Selector PopOver
// row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorUserPopover rowType:XLFormRowDescriptorTypeSelectorPopover title:@"User Popover"];
// row.action.viewControllerClass = [UsersTableViewController class];
// [section addFormRow:row];
// }
self.form = form;
}
return self;
}
- (UIStoryboard *)storyboardForRow:(XLFormRowDescriptor *)formRow
{
return [UIStoryboard storyboardWithName:@"iPhoneStoryboard" bundle:nil];
}
@end
@@ -24,8 +24,11 @@
// THE SOFTWARE.
#import "XLFormRowDescriptor.h"
#import "XLTableViewController.h"
#import "XLRemoteDataStoreController.h"
@interface UsersTableViewController : XLTableViewController <XLFormRowDescriptorViewController, XLFormRowDescriptorPopoverViewController>
@interface UsersTableViewController : XLRemoteDataStoreController <XLFormRowDescriptorViewController, XLFormRowDescriptorPopoverViewController>
@end
@property BOOL isSearchResultsController;
@property NSLayoutConstraint *topConstraint;
@end
@@ -24,9 +24,7 @@
// THE SOFTWARE.
#import "UsersTableViewController.h"
#import "UserLocalDataLoader.h"
#import "UserRemoteDataLoader.h"
#import "User+Additions.h"
#import "HTTPSessionManager.h"
// AFNetworking
#import <AFNetworking/UIImageView+AFNetworking.h>
@@ -65,7 +63,6 @@
// Configure the view for the selected state
}
#pragma mark - Views
-(UIImageView *)userImage
@@ -110,6 +107,7 @@
options:0
metrics:metrics
views:views]];
return result;
}
@@ -117,56 +115,69 @@
@end
@interface UsersTableViewController ()
@interface UsersTableViewController () <UISearchControllerDelegate>
@property (nonatomic, readonly) UsersTableViewController * searchResultController;
@property (nonatomic, readonly) UISearchController * searchController;
@end
@implementation UsersTableViewController
@synthesize rowDescriptor = _rowDescriptor;
@synthesize popoverController = __popoverController;
@synthesize searchController = _searchController;
@synthesize searchResultController = _searchResultController;
static NSString *const kCellIdentifier = @"CellIdentifier";
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
self = [super initWithCoder:coder];
if (self) {
// Custom initialization
[self initialize];
}
return self;
}
-(void)initialize
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
// Enable the pagination
self.loadingPagingEnabled = YES;
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if(self)
{
[self initialize];
}
// Support Search Controller
self.supportSearchController = YES;
[self setLocalDataLoader:[[UserLocalDataLoader alloc] init]];
[self setRemoteDataLoader:[[UserRemoteDataLoader alloc] init]];
// Search
[self setSearchLocalDataLoader:[[UserLocalDataLoader alloc] init]];
[self setSearchRemoteDataLoader:[[UserRemoteDataLoader alloc] init]];
return self;
}
- (void)initialize
{
self.dataLoader = [[XLDataLoader alloc] initWithURLString:@"/mobile/users.json" offsetParamName:@"offset" limitParamName:@"limit" searchStringParamName:@"filter"];
self.dataLoader.delegate = self;
self.dataLoader.storeDelegate = self;
self.dataLoader.limit = 4;
self.dataLoader.collectionKeyPath = @"";
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
// SearchBar
self.tableView.tableHeaderView = self.searchDisplayController.searchBar;
// register cells
[self.searchDisplayController.searchResultsTableView registerClass:[UserCell class] forCellReuseIdentifier:kCellIdentifier];
[self.tableView registerClass:[UserCell class] forCellReuseIdentifier:kCellIdentifier];
self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
[self customizeAppearance];
if (!self.isSearchResultsController){
self.tableView.tableHeaderView = self.searchController.searchBar;
}
else{
[self.tableView setContentInset:UIEdgeInsetsMake(64, 0, 0, 0)];
[self.tableView setScrollIndicatorInsets:self.tableView.contentInset];
}
}
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.searchController.searchBar sizeToFit];
}
#pragma mark - UITableViewDataSource
@@ -174,49 +185,28 @@ static NSString *const kCellIdentifier = @"CellIdentifier";
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UserCell *cell = (UserCell *) [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath:indexPath];;
User * user = nil;
if (tableView == self.tableView){
user = (User *)[self.localDataLoader objectAtIndexPath:indexPath];
}
else{
user = (User *)[self.searchLocalDataLoader objectAtIndexPath:indexPath];
}
NSDictionary *dataItem = [self.dataStore dataAtIndexPath:indexPath];
cell.userName.text = [dataItem valueForKeyPath:@"user.name"];
[cell.userImage setImageWithURL:[NSURL URLWithString:[dataItem valueForKeyPath:@"user.imageURL"]] placeholderImage:[UIImage imageNamed:@"default-avatar"]];
cell.accessoryType = [[self.rowDescriptor.value valueForKeyPath:@"user.id"] isEqual:[dataItem valueForKeyPath:@"user.id"]] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
cell.userName.text = user.userName;
NSMutableURLRequest* imageRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:user.userImageURL]];
[imageRequest setValue:@"image/*" forHTTPHeaderField:@"Accept"];
__typeof__(cell) __weak weakCell = cell;
[cell.userImage setImageWithURLRequest: imageRequest
placeholderImage:[User defaultProfileImage]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if (image) {
[weakCell.userImage setImage:image];
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
cell.accessoryType = [[self.rowDescriptor.value formValue] isEqual:user.userId] ? UITableViewCellAccessoryCheckmark : UITableViewCellAccessoryNone;
return cell;
}
#pragma mark - UITableViewDelegate
- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 73.0f;
}
#pragma mark - UITableViewDelegate
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
User * user = nil;
if (tableView == self.tableView){
user = (User *)[self.localDataLoader objectAtIndexPath:indexPath];
}
else{
user = (User *)[self.searchLocalDataLoader objectAtIndexPath:indexPath];
}
self.rowDescriptor.value = user;
NSDictionary *dataItem = [self.dataStore dataAtIndexPath:indexPath];
self.rowDescriptor.value = dataItem;
if (self.popoverController){
[self.popoverController dismissPopoverAnimated:YES];
@@ -227,19 +217,36 @@ static NSString *const kCellIdentifier = @"CellIdentifier";
}
}
#pragma mark - XLDataLoaderDelegate
#pragma mark - Helpers
-(void)customizeAppearance
-(AFHTTPSessionManager *)sessionManagerForDataLoader:(XLDataLoader *)dataLoader
{
[[self navigationItem] setTitle:@"Select a User"];
return [HTTPSessionManager sharedClient];
}
#pragma mark - UISearchController
-(UISearchController *)searchController
{
if (_searchController) return _searchController;
[self.tableView setBackgroundColor:[UIColor colorWithWhite:0.9 alpha:1.0]];
[self.tableView setTableFooterView:[[UIView alloc] initWithFrame:CGRectZero]];
[self.searchDisplayController.searchResultsTableView setBackgroundColor:[UIColor colorWithWhite:0.9 alpha:1.0]];
[self.searchDisplayController.searchResultsTableView setTableFooterView:[[UIView alloc] initWithFrame:CGRectZero]];
self.definesPresentationContext = YES;
_searchController = [[UISearchController alloc] initWithSearchResultsController:self.searchResultController];
_searchController.delegate = self;
_searchController.searchResultsUpdater = self.searchResultController;
_searchController.searchBar.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[_searchController.searchBar sizeToFit];
return _searchController;
}
@end
-(UsersTableViewController *)searchResultController
{
if (_searchResultController) return _searchResultController;
_searchResultController = [[UsersTableViewController alloc]init];
_searchResultController.dataLoader.limit = 0; // no paging in search result
_searchResultController.isSearchResultsController = YES;
return _searchResultController;
}
@end
@@ -1,53 +0,0 @@
//
// CoreDataStore.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 <CoreData/CoreData.h>
#import <Foundation/Foundation.h>
@interface CoreDataStore : NSObject
+(id)defaultStore;
+ (NSManagedObjectContext *)mainQueueContext;
+ (NSManagedObjectContext *)privateQueueContext;
+ (void)savePrivateQueueContext;
+ (void)saveMainQueueContext;
+ (NSManagedObjectID *)managedObjectIDFromString:(NSString *)managedObjectIDString;
@end
@interface NSManagedObject (Additions)
+(instancetype)findFirstByAttribute:(NSString *)attribute withValue:(id)value inContext:(NSManagedObjectContext *)context;
+(NSFetchRequest*)fetchRequest;
+(instancetype)insert:(NSManagedObjectContext *)context;
@end
@@ -1,227 +0,0 @@
//
// CoreDataStore.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 "CoreDataStore.h"
static NSString *const TBCoreDataModelFileName = @"Model";
@interface CoreDataStore ()
@property (strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property (strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (strong, nonatomic) NSManagedObjectContext *mainQueueContext;
@property (strong, nonatomic) NSManagedObjectContext *privateQueueContext;
@end
@implementation CoreDataStore
+ (instancetype)defaultStore {
static CoreDataStore *_defaultStore = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_defaultStore = [[self alloc] init];
});
return _defaultStore;
}
#pragma mark - Singleton Access
+ (NSManagedObjectContext *)mainQueueContext
{
return [[self defaultStore] mainQueueContext];
}
+ (NSManagedObjectContext *)privateQueueContext
{
return [[self defaultStore] privateQueueContext];
}
+(void)savePrivateQueueContext
{
NSError * error;
[[self privateQueueContext] save:&error];
NSAssert(!error, [error localizedDescription]);
}
+ (void)saveMainQueueContext
{
NSError * error;
[[self mainQueueContext] save:&error];
NSAssert(!error, [error localizedDescription]);
}
+ (NSManagedObjectID *)managedObjectIDFromString:(NSString *)managedObjectIDString
{
return [[[self defaultStore] persistentStoreCoordinator] managedObjectIDForURIRepresentation:[NSURL URLWithString:managedObjectIDString]];
}
#pragma mark - Lifecycle
- (id)init
{
self = [super init];
if (self) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSavePrivateQueueContext:)name:NSManagedObjectContextDidSaveNotification object:[self privateQueueContext]];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextDidSaveMainQueueContext:) name:NSManagedObjectContextDidSaveNotification object:[self mainQueueContext]];
}
return self;
}
- (void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
#pragma mark - Notifications
- (void)contextDidSavePrivateQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.mainQueueContext performBlock:^{
for(NSManagedObject *object in [[notification userInfo] objectForKey:NSUpdatedObjectsKey]) {
[[self.mainQueueContext objectWithID:[object objectID]] willAccessValueForKey:nil];
}
[self.mainQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
- (void)contextDidSaveMainQueueContext:(NSNotification *)notification
{
@synchronized(self) {
[self.privateQueueContext performBlock:^{
[self.privateQueueContext mergeChangesFromContextDidSaveNotification:notification];
}];
}
}
#pragma mark - Getters
- (NSManagedObjectContext *)mainQueueContext
{
if (!_mainQueueContext) {
_mainQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_mainQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
return _mainQueueContext;
}
- (NSManagedObjectContext *)privateQueueContext
{
if (!_privateQueueContext) {
_privateQueueContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
_privateQueueContext.persistentStoreCoordinator = self.persistentStoreCoordinator;
}
return _privateQueueContext;
}
#pragma mark - Stack Setup
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (!_persistentStoreCoordinator) {
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];
NSError *error = nil;
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self persistentStoreURL] options:[self persistentStoreOptions] error:&error]) {
NSLog(@"Error adding persistent store. %@, %@", error, error.userInfo);
}
}
return _persistentStoreCoordinator;
}
- (NSManagedObjectModel *)managedObjectModel
{
if (!_managedObjectModel) {
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:TBCoreDataModelFileName withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
}
return _managedObjectModel;
}
- (NSURL *)persistentStoreURL
{
return [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Model.sqlite"];
}
- (NSDictionary *)persistentStoreOptions
{
return @{NSInferMappingModelAutomaticallyOption: @YES, NSMigratePersistentStoresAutomaticallyOption: @YES, NSSQLitePragmasOption: @{@"synchronous": @"OFF"}};
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
@end
@implementation NSManagedObject (Additions)
+(instancetype)findFirstByAttribute:(NSString *)attribute withValue:(id)value inContext:(NSManagedObjectContext *)context
{
NSString * predicateStr = [NSString stringWithFormat:@"%@ = %%@", attribute];
NSPredicate * searchByAttValue = [NSPredicate predicateWithFormat:predicateStr argumentArray:@[value]];
NSFetchRequest * fetchRequest = [self fetchRequest];
fetchRequest.predicate = searchByAttValue;
fetchRequest.fetchLimit = 1;
NSArray *result = [context executeFetchRequest:fetchRequest error:nil];
return [result lastObject];
}
+(NSFetchRequest*)fetchRequest
{
return [NSFetchRequest fetchRequestWithEntityName:NSStringFromClass(self)];
}
+(NSEntityDescription*)entityDescriptor:(NSManagedObjectContext *)context
{
return [NSEntityDescription entityForName:NSStringFromClass(self) inManagedObjectContext:context];
}
+(instancetype)insert:(NSManagedObjectContext *)context
{
return [[NSManagedObject alloc] initWithEntity:[self entityDescriptor:context] insertIntoManagedObjectContext:context];
}
@end
@@ -1,41 +0,0 @@
//
// User+Additions.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 "User.h"
@interface User (Additions) <XLFormOptionObject>
+ (User *)createOrUpdateWithServiceResult:(NSDictionary *)data inContext:(NSManagedObjectContext *)context;
+ (UIImage *)defaultProfileImage;
+ (NSPredicate *)getPredicateBySearchInput:(NSString *)search;
+ (NSFetchRequest *)getFetchRequest;
+ (NSFetchRequest *)getFetchRequestBySearchInput:(NSString *)search;
@end
@@ -1,87 +0,0 @@
//
// User+Additions.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 "CoreDataStore.h"
#import "User+Additions.h"
#define USER_ID @"id"
#define USER_IMAGE_URL @"imageURL"
#define USER_NAME @"name"
@implementation User (Additions)
+ (User *)createOrUpdateWithServiceResult:(NSDictionary *)data inContext:(NSManagedObjectContext *)context;
{
User *user = [User findFirstByAttribute:@"userId" withValue:data[USER_ID] inContext:context];
if (!user)
{
user = [User insert:context];
}
user.userId = data[USER_ID];
user.userImageURL = data[USER_IMAGE_URL] ;
user.userName = data[USER_NAME];
return user;
}
+ (UIImage *)defaultProfileImage
{
return [UIImage imageNamed:@"default-avatar"];
}
+ (NSPredicate *)getPredicateBySearchInput:(NSString *)search {
if (search && ![search isEqualToString:@""]) {
return [NSPredicate predicateWithFormat:@"userName CONTAINS[cd] %@" , search];
}
return nil;
}
+ (NSFetchRequest *)getFetchRequest {
return [User getFetchRequestBySearchInput:nil];
}
+ (NSFetchRequest *)getFetchRequestBySearchInput:(NSString *)search {
NSFetchRequest * fetchRequest = [User fetchRequest];
fetchRequest.predicate = [User getPredicateBySearchInput:search];
fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"userName" ascending:YES selector:@selector(caseInsensitiveCompare:)]];
return fetchRequest;
}
#pragma mark - XLFormOptionObject
-(NSString *)formDisplayText
{
return self.userName;
}
-(id)formValue
{
return self.userId;
}
@end
@@ -1,36 +0,0 @@
//
// User.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 <CoreData/CoreData.h>
@interface User : NSManagedObject
@property (nonatomic, retain) NSNumber * userId;
@property (nonatomic, retain) NSString * userName;
@property (nonatomic, retain) NSString * userImageURL;
@end
@@ -1,35 +0,0 @@
//
// User.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 "User.h"
@implementation User
@dynamic userId;
@dynamic userName;
@dynamic userImageURL;
@end
@@ -1,30 +0,0 @@
//
// UserLocalDataLoader.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 "XLLocalDataLoader.h"
@interface UserLocalDataLoader : XLLocalDataLoader
@end
@@ -1,60 +0,0 @@
//
// UserLocalDataLoader.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 "UserLocalDataLoader.h"
#import "User+Additions.h"
#import "CoreDataStore.h"
@implementation UserLocalDataLoader
{
NSString *_searchString;
}
- (id)init {
self = [super init];
if (self) {
NSFetchedResultsController * fetchResultController = [[NSFetchedResultsController alloc] initWithFetchRequest:[User getFetchRequest]
managedObjectContext:[CoreDataStore mainQueueContext]
sectionNameKeyPath:nil
cacheName:nil];
[self setFetchedResultsController:fetchResultController];
}
return self;
}
-(void)changeSearchString:(NSString *)searchString
{
_searchString = searchString;
[self refreshPredicate];
}
- (void)refreshPredicate
{
[self setPredicate:[User getPredicateBySearchInput:_searchString]];
}
@end
@@ -1,30 +0,0 @@
//
// UserRemoteDataLoader.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 "XLRemoteDataLoader.h"
@interface UserRemoteDataLoader : XLRemoteDataLoader
@end
@@ -1,107 +0,0 @@
//
// UserRemoteDataLoader.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 "UserRemoteDataLoader.h"
#import "HTTPSessionManager.h"
#import "CoreDataStore.h"
#import "User+Additions.h"
@implementation UserRemoteDataLoader
-(NSString *)URLString
{
return @"/mobile/users.json";
}
-(NSDictionary *)parameters
{
NSString *filterParam = self.searchString ?: @"";
return @{@"filter" : filterParam,
@"offset" : @(self.offset),
@"limit" : @(self.limit)};
}
-(AFHTTPSessionManager *)sessionManager
{
return [HTTPSessionManager sharedClient];
}
-(void)successulDataLoad {
// change flags
// [self fetchedData] contains the data coming from the server
NSArray * itemsArray = [[self fetchedData] objectForKey:kXLRemoteDataLoaderDefaultKeyForNonDictionaryResponse];
// This flag indicates if there is more data to load
_hasMoreToLoad = !((itemsArray.count == 0) || (itemsArray.count < _limit && itemsArray.count != 0));
[[CoreDataStore privateQueueContext] performBlock:^{
for (NSDictionary *item in itemsArray) {
// Creates or updates the User and the user who created it with the data that came from the server
[User createOrUpdateWithServiceResult:item[@"user"] inContext:[CoreDataStore privateQueueContext]];
}
[self removeOutdatedData:itemsArray inContext:[CoreDataStore privateQueueContext]];
[CoreDataStore savePrivateQueueContext];
}];
[super successulDataLoad];
}
#pragma mark - Auxiliary Functions
- (void)removeOutdatedData:(NSArray *)data inContext:(NSManagedObjectContext *)context
{
// First, remove older data
NSFetchRequest * fetchRequest = [User getFetchRequestBySearchInput:self.searchString];
fetchRequest.fetchLimit = self.limit;
fetchRequest.fetchOffset = self.offset;
NSError *error;
NSArray * oldObjects = [context executeFetchRequest:fetchRequest error:&error];
NSArray * arrayToIterate = [oldObjects copy];
if (error) {
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Error"
message:error.localizedFailureReason ?: error.localizedDescription
delegate:nil
cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil];
[alertView show];
});
return;
}
for (User *user in arrayToIterate)
{
NSArray *filteredArray = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"user.id == %@" argumentArray:@[user.userId]]];
if (filteredArray.count == 0) {
// This User no longer exists
[context deleteObject:user];
}
}
}
@end
@@ -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="7531" systemVersion="14D131" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="p4n-1v-pzo">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14E46" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="p4n-1v-pzo">
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7520"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
</dependencies>
<scenes>
<!--Navigation Controller-->
@@ -32,7 +32,7 @@
<viewControllerLayoutGuide type="bottom" id="HPb-Nx-E1G"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="wpr-wE-9nj">
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -130,7 +130,7 @@
<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="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -186,7 +186,7 @@
<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="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -206,7 +206,7 @@
<viewControllerLayoutGuide type="bottom" id="CTu-Y5-7Qw"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="bNj-SD-83w">
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -229,7 +229,7 @@
<viewControllerLayoutGuide type="bottom" id="cgQ-Vs-ICN"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="JjC-E5-SyY">
<rect key="frame" x="0.0" y="0.0" width="320" height="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -256,7 +256,7 @@
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="eqB-vl-BzH" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="588" y="-635"/>
<point key="canvasLocation" x="586" y="-654"/>
</scene>
<!--Basic Predicate View Controller-->
<scene sceneID="pD4-sm-x3a">
@@ -267,7 +267,7 @@
<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="504"/>
<rect key="frame" x="0.0" y="64" width="320" height="504"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
@@ -278,6 +278,40 @@
</objects>
<point key="canvasLocation" x="-159" y="1151"/>
</scene>
<!--Users Table View Controller-->
<scene sceneID="lGi-0L-kUk">
<objects>
<viewController storyboardIdentifier="UsersTableViewController" automaticallyAdjustsScrollViewInsets="NO" definesPresentationContext="YES" modalPresentationStyle="currentContext" id="MON-q2-1DB" customClass="UsersTableViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="at2-Ds-EcY"/>
<viewControllerLayoutGuide type="bottom" id="uVG-bI-IMr"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="sMH-hT-NCg">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<tableView autoresizesSubviews="NO" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" translatesAutoresizingMaskIntoConstraints="NO" id="fLo-Gu-rqr">
<rect key="frame" x="0.0" y="20" width="320" height="548"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="uVG-bI-IMr" firstAttribute="top" secondItem="fLo-Gu-rqr" secondAttribute="bottom" id="25A-HG-wek"/>
<constraint firstItem="fLo-Gu-rqr" firstAttribute="top" secondItem="at2-Ds-EcY" secondAttribute="bottom" id="3N4-a2-LLf"/>
<constraint firstAttribute="trailing" secondItem="fLo-Gu-rqr" secondAttribute="trailing" id="IXV-p6-sAw"/>
<constraint firstItem="fLo-Gu-rqr" firstAttribute="leading" secondItem="sMH-hT-NCg" secondAttribute="leading" id="Xjr-w6-wlu"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="LIq-iZ-ILx"/>
<connections>
<outlet property="tableView" destination="fLo-Gu-rqr" id="2ES-0n-eVG"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="flB-2M-8zS" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1346" y="1178"/>
</scene>
</scenes>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
@@ -285,6 +319,6 @@
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
<inferredMetricsTieBreakers>
<segue reference="wAD-tS-AFZ"/>
<segue reference="Mtw-x2-E0b"/>
</inferredMetricsTieBreakers>
</document>
@@ -89,7 +89,7 @@ NSString * const kValidationInteger = @"kInteger";
// number Section
section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Numbers"];
section.footerTitle = @"grather than 50 and less than 100";
section.footerTitle = @"greater than 50 and less than 100";
[formDescriptor addFormSection:section];
// Integer
@@ -97,7 +97,7 @@ NSString * const kValidationInteger = @"kInteger";
[row.cellConfigAtConfigure setObject:@"Required..." forKey:@"textField.placeholder"];
[row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
row.required = YES;
[row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"grather than 50 and less than 100" regex:@"^([5-9][0-9]|100)$"]];
[row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"greater than 50 and less than 100" regex:@"^([5-9][0-9]|100)$"]];
[section addFormRow:row];
self.form = formDescriptor;
+2 -2
View File
@@ -1,10 +1,10 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '7.0'
platform :ios, '8.0'
pod 'XLForm', :path => '../../'
#Following pods are used for custom row examples
pod 'AFNetworking', '~> 2.0', :inhibit_warnings => true
pod 'XLDataLoader', '~> 1.1', :inhibit_warnings => true
pod 'XLData', :git => 'https://github.com/xmartlabs/XLData.git', :commit => '1f9019b56242a2019c7f7e11ec4ef823c397ebcf', :inhibit_warnings => true
pod 'JVFloatLabeledTextField', '1.0.2', :inhibit_warnings => true
pod 'AXRatingView', '1.0.3', :inhibit_warnings => true
@@ -27,13 +27,6 @@
28815E2E1A8589F600B674D2 /* MapViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28815E2D1A8589F600B674D2 /* MapViewController.xib */; };
28A7661F193248BD00D69546 /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 28A7661E193248BD00D69546 /* CoreData.framework */; };
28A76625193251E500D69546 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A76624193251E500D69546 /* AppDelegate.m */; };
28A7662E1932E98A00D69546 /* HTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A7662D1932E98A00D69546 /* HTTPSessionManager.m */; };
28A7663B1932EA1F00D69546 /* UserLocalDataLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A766361932EA1F00D69546 /* UserLocalDataLoader.m */; };
28A7663C1932EA1F00D69546 /* UserRemoteDataLoader.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A766381932EA1F00D69546 /* UserRemoteDataLoader.m */; };
28A766451932EC9C00D69546 /* CoreDataStore.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A766401932EC9C00D69546 /* CoreDataStore.m */; };
28A766461932EC9C00D69546 /* User+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A766421932EC9C00D69546 /* User+Additions.m */; };
28A7664A1932ED3400D69546 /* Model.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 28A766481932ED3400D69546 /* Model.xcdatamodeld */; };
28A7664D1932EE0B00D69546 /* User.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A7664C1932EE0B00D69546 /* User.m */; };
28A766551932F22400D69546 /* UsersTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A766541932F22400D69546 /* UsersTableViewController.m */; };
28A7665E1932F61100D69546 /* DynamicSelectorsFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A7665D1932F61100D69546 /* DynamicSelectorsFormViewController.m */; };
28A8083E190D9083009D77F8 /* iPhoneStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 28A8083D190D9083009D77F8 /* iPhoneStoryboard.storyboard */; };
@@ -54,6 +47,7 @@
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 */; };
DEA6EF911B57D6CC000F4893 /* HTTPSessionManager.m in Sources */ = {isa = PBXBuildFile; fileRef = DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
@@ -92,19 +86,6 @@
28815E2D1A8589F600B674D2 /* MapViewController.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = MapViewController.xib; path = Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.xib; sourceTree = "<group>"; };
28A7661E193248BD00D69546 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
28A76624193251E500D69546 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AppDelegate.m; path = Examples/AppDelegate.m; sourceTree = "<group>"; };
28A7662C1932E98A00D69546 /* HTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSessionManager.h; path = Examples/Selectors/Helpers/HTTPSessionManager.h; sourceTree = "<group>"; };
28A7662D1932E98A00D69546 /* HTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPSessionManager.m; path = Examples/Selectors/Helpers/HTTPSessionManager.m; sourceTree = "<group>"; };
28A766351932EA1F00D69546 /* UserLocalDataLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserLocalDataLoader.h; sourceTree = "<group>"; };
28A766361932EA1F00D69546 /* UserLocalDataLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserLocalDataLoader.m; sourceTree = "<group>"; };
28A766371932EA1F00D69546 /* UserRemoteDataLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UserRemoteDataLoader.h; sourceTree = "<group>"; };
28A766381932EA1F00D69546 /* UserRemoteDataLoader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UserRemoteDataLoader.m; sourceTree = "<group>"; };
28A7663F1932EC9C00D69546 /* CoreDataStore.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CoreDataStore.h; sourceTree = "<group>"; };
28A766401932EC9C00D69546 /* CoreDataStore.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CoreDataStore.m; sourceTree = "<group>"; };
28A766411932EC9C00D69546 /* User+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "User+Additions.h"; sourceTree = "<group>"; };
28A766421932EC9C00D69546 /* User+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "User+Additions.m"; sourceTree = "<group>"; };
28A766491932ED3400D69546 /* Model.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Model.xcdatamodel; sourceTree = "<group>"; };
28A7664B1932EE0B00D69546 /* User.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = User.h; sourceTree = "<group>"; };
28A7664C1932EE0B00D69546 /* User.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = User.m; sourceTree = "<group>"; };
28A766531932F22400D69546 /* UsersTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UsersTableViewController.h; path = Examples/Selectors/DynamicSelector/UsersTableViewController.h; sourceTree = "<group>"; };
28A766541932F22400D69546 /* UsersTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UsersTableViewController.m; path = Examples/Selectors/DynamicSelector/UsersTableViewController.m; sourceTree = "<group>"; };
28A7665C1932F61100D69546 /* DynamicSelectorsFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DynamicSelectorsFormViewController.h; path = Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.h; sourceTree = "<group>"; };
@@ -141,6 +122,8 @@
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>"; };
DEA6EF8F1B57D6CC000F4893 /* HTTPSessionManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = HTTPSessionManager.h; path = Examples/Selectors/HTTPSessionManager.h; sourceTree = "<group>"; };
DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = HTTPSessionManager.m; path = Examples/Selectors/HTTPSessionManager.m; sourceTree = "<group>"; };
F6DF43B7BBF44F72A4493E8E /* libPods.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPods.a; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -223,7 +206,6 @@
children = (
283B59AF19531DDA000828CD /* CustomSelectors */,
28A766521932F1FA00D69546 /* DynamicSelector */,
28A7662B1932E92D00D69546 /* Helpers */,
2843EB4918D496F600F13E2B /* SelectorsFormViewController.h */,
2843EB4A18D496F600F13E2B /* SelectorsFormViewController.m */,
);
@@ -355,55 +337,10 @@
name = CustomCells;
sourceTree = "<group>";
};
28A7662B1932E92D00D69546 /* Helpers */ = {
isa = PBXGroup;
children = (
28A7663D1932EC9C00D69546 /* Data */,
28A766301932EA1F00D69546 /* DataLoaders */,
28A7662C1932E98A00D69546 /* HTTPSessionManager.h */,
28A7662D1932E98A00D69546 /* HTTPSessionManager.m */,
);
name = Helpers;
sourceTree = "<group>";
};
28A766301932EA1F00D69546 /* DataLoaders */ = {
isa = PBXGroup;
children = (
28A766351932EA1F00D69546 /* UserLocalDataLoader.h */,
28A766361932EA1F00D69546 /* UserLocalDataLoader.m */,
28A766371932EA1F00D69546 /* UserRemoteDataLoader.h */,
28A766381932EA1F00D69546 /* UserRemoteDataLoader.m */,
);
name = DataLoaders;
path = Examples/Selectors/Helpers/DataLoaders;
sourceTree = "<group>";
};
28A7663D1932EC9C00D69546 /* Data */ = {
isa = PBXGroup;
children = (
28A7663E1932EC9C00D69546 /* Store */,
28A766411932EC9C00D69546 /* User+Additions.h */,
28A766421932EC9C00D69546 /* User+Additions.m */,
28A766481932ED3400D69546 /* Model.xcdatamodeld */,
28A7664B1932EE0B00D69546 /* User.h */,
28A7664C1932EE0B00D69546 /* User.m */,
);
name = Data;
path = Examples/Selectors/Helpers/Data;
sourceTree = "<group>";
};
28A7663E1932EC9C00D69546 /* Store */ = {
isa = PBXGroup;
children = (
28A7663F1932EC9C00D69546 /* CoreDataStore.h */,
28A766401932EC9C00D69546 /* CoreDataStore.m */,
);
path = Store;
sourceTree = "<group>";
};
28A766521932F1FA00D69546 /* DynamicSelector */ = {
isa = PBXGroup;
children = (
DEA6EF8E1B57D698000F4893 /* SessionManager */,
28A7665A1932F55700D69546 /* XLFormRowViewController */,
28A7665C1932F61100D69546 /* DynamicSelectorsFormViewController.h */,
28A7665D1932F61100D69546 /* DynamicSelectorsFormViewController.m */,
@@ -502,6 +439,15 @@
path = Examples/PredicateDisabling;
sourceTree = "<group>";
};
DEA6EF8E1B57D698000F4893 /* SessionManager */ = {
isa = PBXGroup;
children = (
DEA6EF8F1B57D6CC000F4893 /* HTTPSessionManager.h */,
DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */,
);
name = SessionManager;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -608,15 +554,12 @@
283B59B7195334AF000828CD /* CustomSelectorsFormViewController.m in Sources */,
28A766551932F22400D69546 /* UsersTableViewController.m in Sources */,
3CDAFC7A1AB0AFA4000F75B6 /* CustomRowsViewController.m in Sources */,
28A7663B1932EA1F00D69546 /* UserLocalDataLoader.m in Sources */,
DEA6EF911B57D6CC000F4893 /* HTTPSessionManager.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 */,
28A7664A1932ED3400D69546 /* Model.xcdatamodeld in Sources */,
3C3B01F01AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m in Sources */,
28A766461932EC9C00D69546 /* User+Additions.m in Sources */,
28DBB04118D76FDC00FB8A8B /* MultivaluedFormViewController.m in Sources */,
28A85D5918E346C100E81A26 /* XLFormImageSelectorCell.m in Sources */,
28468E9818EC686500DBB015 /* NativeEventFormViewController.m in Sources */,
@@ -629,12 +572,9 @@
2843EB5618D4F7B700F13E2B /* DatesFormViewController.m in Sources */,
283C6B7D1999BAF100A5283D /* UICustomizationFormViewController.m in Sources */,
3C3B01E21AB7499A0027CD45 /* XLRatingView.m in Sources */,
28A7662E1932E98A00D69546 /* HTTPSessionManager.m in Sources */,
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 */,
@@ -697,7 +637,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
@@ -729,7 +669,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 7.0;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
@@ -744,7 +684,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "XLForm/XLForm-Prefix.pch";
INFOPLIST_FILE = "XLForm/XLForm-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
@@ -760,7 +700,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "XLForm/XLForm-Prefix.pch";
INFOPLIST_FILE = "XLForm/XLForm-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 7.1;
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)";
TARGETED_DEVICE_FAMILY = "1,2";
WRAPPER_EXTENSION = app;
@@ -789,19 +729,6 @@
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
28A766481932ED3400D69546 /* Model.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
28A766491932ED3400D69546 /* Model.xcdatamodel */,
);
currentVersion = 28A766491932ED3400D69546 /* Model.xcdatamodel */;
path = Model.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
};
/* End XCVersionGroup section */
};
rootObject = 2850C5F018D0F706002B7D0A /* Project object */;
}
@@ -17,11 +17,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>2.0.1</string>
<string>3.0.1</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>2.0.1</string>
<string>3.0.1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
@@ -170,7 +170,7 @@ NSString * kAccessoryViewNotes = @"notes";
[row.cellConfigAtConfigure setObject:@"TEXT VIEW EXAMPLE" forKey:@"textView.placeholder"];
[section addFormRow:row];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Ckeck"];
row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Check"];
[section addFormRow:row];
section = [XLFormSectionDescriptor formSectionWithTitle:@"TextView With Label Example"];
@@ -80,7 +80,7 @@ class CustomRowsViewController : XLFormViewController {
form.addFormSection(section)
// WeekDays
row = XLFormRowDescriptor(tag: Tags.CustomRowWeekdays.rawValue, rowType: XLFormRowDescriptorTypeWeekDays, title: nil)
row = XLFormRowDescriptor(tag: Tags.CustomRowWeekdays.rawValue, rowType: XLFormRowDescriptorTypeWeekDays)
row.value = [
XLFormWeekDaysCell.kWeekDay.Sunday.description(): false,
XLFormWeekDaysCell.kWeekDay.Monday.description(): true,
@@ -53,7 +53,7 @@ class FloatLabeledTextFieldCell : XLFormBaseCell, UITextFieldDelegate {
override func update() {
super.update()
self.floatLabeledTextField.attributedPlaceholder = NSAttributedString(string: self.rowDescriptor.title, attributes: [NSForegroundColorAttributeName: UIColor.lightGrayColor()])
self.floatLabeledTextField.attributedPlaceholder = NSAttributedString(string: self.rowDescriptor.title ?? "" , attributes: [NSForegroundColorAttributeName: UIColor.lightGrayColor()])
if let value: AnyObject = self.rowDescriptor.value {
self.floatLabeledTextField.text = value.displayText()
@@ -27,20 +27,20 @@ class XLRatingView : AXRatingView {
override init(frame: CGRect) {
super.init(frame: frame)
setTranslatesAutoresizingMaskIntoConstraints(false)
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setTranslatesAutoresizingMaskIntoConstraints(false)
}
func customize() {
self.baseColor = UIColor(red: (205/255.0), green: (201/255.0), blue: (201/255.0), alpha: 1)
self.highlightColor = UIColor(red: (255/255.0), green: (215/255.0), blue: 0, alpha: 1)
self.markFont = UIFont.systemFontOfSize(23.0)
self.setTranslatesAutoresizingMaskIntoConstraints(false)
self.stepInterval = 1.0
baseColor = UIColor(red: (205/255.0), green: (201/255.0), blue: (201/255.0), alpha: 1)
highlightColor = UIColor(red: (255/255.0), green: (215/255.0), blue: 0, alpha: 1)
markFont = UIFont.systemFontOfSize(23.0)
stepInterval = 1.0
}
}
@@ -41,16 +41,16 @@ class XLFormRatingCell : XLFormBaseCell {
override func update() {
super.update()
self.ratingView.value = self.rowDescriptor.value.floatValue
self.rateTitle.text = self.rowDescriptor.title
self.ratingView.alpha = self.rowDescriptor.isDisabled() ? 0.6 : 1
self.rateTitle.alpha = self.rowDescriptor.isDisabled() ? 0.6 : 1
self.ratingView.value = self.rowDescriptor!.value!.floatValue
self.rateTitle.text = self.rowDescriptor!.title
self.ratingView.alpha = self.rowDescriptor!.isDisabled() ? 0.6 : 1
self.rateTitle.alpha = self.rowDescriptor!.isDisabled() ? 0.6 : 1
}
//MARK: Events
func rateChanged(ratingView : XLRatingView){
self.rowDescriptor.value = ratingView.value
self.rowDescriptor!.value = ratingView.value
}
}
@@ -100,9 +100,9 @@ class XLFormWeekDaysCell : XLFormBaseCell {
@IBAction func dayTapped(sender: UIButton) {
let day = getDayFormButton(sender)
sender.selected = !sender.selected
var newValue = rowDescriptor.value as! Dictionary<String, Bool>
var newValue = rowDescriptor!.value as! Dictionary<String, Bool>
newValue[day] = sender.selected
rowDescriptor.value = newValue
rowDescriptor!.value = newValue
}
//MARK: - Helpers
@@ -120,7 +120,7 @@ class XLFormWeekDaysCell : XLFormBaseCell {
}
func updateButtons() {
var value = rowDescriptor.value as! Dictionary<String, Bool>
var value = rowDescriptor!.value as! Dictionary<String, Bool>
sundayButton.selected = value[XLFormWeekDaysCell.kWeekDay.Sunday.description()]!
mondayButton.selected = value[XLFormWeekDaysCell.kWeekDay.Monday.description()]!
@@ -130,7 +130,7 @@ class XLFormWeekDaysCell : XLFormBaseCell {
fridayButton.selected = value[XLFormWeekDaysCell.kWeekDay.Friday.description()]!
saturdayButton.selected = value[XLFormWeekDaysCell.kWeekDay.Saturday.description()]!
sundayButton.alpha = rowDescriptor.isDisabled() ? 0.6 : 1
sundayButton.alpha = rowDescriptor!.isDisabled() ? 0.6 : 1
mondayButton.alpha = mondayButton.alpha
tuesdayButton.alpha = mondayButton.alpha
wednesdayButton.alpha = mondayButton.alpha
@@ -95,18 +95,28 @@ class PredicateFormViewController : XLFormViewController {
section.addFormRow(row)
row.hidden = NSPredicate(format: "$\(Tags.Date.rawValue).isDisabled == 1 AND $\(Tags.Text.rawValue).value contains[c] 'Out'")
row.onChangeBlock = {
let noValue = "No Value"
let message = "Old value: \($0 ?? noValue), New value: \($1 ?? noValue)"
let alertView = UIAlertController(title: "Account Field changed", message: message, preferredStyle: UIAlertControllerStyle.ActionSheet)
alertView.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
let row = $2
self.navigationController?.presentViewController(alertView, animated: true, completion: nil)
}
self.form = form
}
}
@@ -115,11 +115,11 @@ class User: NSObject, XLFormOptionObject {
self.userName = userName
}
func formDisplayText() -> String! {
func formDisplayText() -> String {
return self.userName
}
func formValue() -> AnyObject! {
func formValue() -> AnyObject {
return self.userId
}
@@ -172,7 +172,7 @@ class UsersTableViewController : UITableViewController, XLFormRowDescriptorViewC
cell.userName.text = userData["name"] as? String
cell.userImage.image = UIImage(named: (userData["imageName"] as? String)!)
if self.rowDescriptor?.value != nil {
cell.accessoryType = self.rowDescriptor!.value.formValue().isEqual(userId) ? UITableViewCellAccessoryType.Checkmark : UITableViewCellAccessoryType.None
cell.accessoryType = self.rowDescriptor!.value!.formValue().isEqual(userId) ? .Checkmark : .None
}
return cell;
@@ -93,7 +93,7 @@ NSString * const kValidationInteger = @"kInteger";
// number Section
section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Numbers"];
section.footerTitle = @"grather than 50 and less than 100";
section.footerTitle = @"greater than 50 and less than 100";
[formDescriptor addFormSection:section];
// Integer
@@ -101,7 +101,7 @@ NSString * const kValidationInteger = @"kInteger";
[row.cellConfigAtConfigure setObject:@"Required..." forKey:@"textField.placeholder"];
[row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
row.required = YES;
[row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"grather than 50 and less than 100" regex:@"^([5-9][0-9]|100)$"]];
[row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"greater than 50 and less than 100" regex:@"^([5-9][0-9]|100)$"]];
[section addFormRow:row];
self.form = formDescriptor;
@@ -511,7 +511,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
@@ -548,7 +548,7 @@
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 8.2;
IPHONEOS_DEPLOYMENT_TARGET = 8.4;
MTL_ENABLE_DEBUG_INFO = NO;
SDKROOT = iphoneos;
TARGETED_DEVICE_FAMILY = "1,2";
@@ -138,11 +138,11 @@ class AccessoryViewFormViewController : XLFormViewController {
row = XLFormRowDescriptor(tag: Tags.AccessoryViewTextView.rawValue, rowType:XLFormRowDescriptorTypeTextView, title: nil)
row = XLFormRowDescriptor(tag: Tags.AccessoryViewTextView.rawValue, rowType:XLFormRowDescriptorTypeTextView)
row.cellConfigAtConfigure["textView.placeholder"] = "TEXT VIEW EXAMPLE"
section.addFormRow(row)
row = XLFormRowDescriptor(tag: Tags.AccessoryViewCheck.rawValue, rowType:XLFormRowDescriptorTypeBooleanCheck, title:"Ckeck")
row = XLFormRowDescriptor(tag: Tags.AccessoryViewCheck.rawValue, rowType:XLFormRowDescriptorTypeBooleanCheck, title:"Check")
section.addFormRow(row)
section = XLFormSectionDescriptor()
@@ -168,7 +168,7 @@ class AccessoryViewFormViewController : XLFormViewController {
override func formRowDescriptorValueHasChanged(formRow: XLFormRowDescriptor!, oldValue: AnyObject!, newValue: AnyObject!) {
super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
if formRow.tag == Tags.AccessoryViewRowNavigationStopDisableRow.rawValue {
if formRow.value.boolValue == true {
if formRow.value!.boolValue == true {
self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptions.StopDisableRow
}
else{
@@ -176,7 +176,7 @@ class AccessoryViewFormViewController : XLFormViewController {
}
}
else if formRow.tag == Tags.AccessoryViewRowNavigationStopInlineRow.rawValue {
if formRow.value.boolValue == true {
if formRow.value!.boolValue == true {
self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptions.StopInlineRow
}
else{
@@ -184,7 +184,7 @@ class AccessoryViewFormViewController : XLFormViewController {
}
}
else if formRow.tag == Tags.AccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow.rawValue {
if formRow.value.boolValue == true {
if formRow.value!.boolValue == true {
self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptions.SkipCanNotBecomeFirstResponderRow
}
else{
@@ -23,6 +23,7 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import MapKit
class MapAnnotation : NSObject, MKAnnotation {
@@ -41,7 +42,7 @@ class MapViewController : UIViewController, XLFormRowDescriptorViewController, M
var rowDescriptor: XLFormRowDescriptor?
lazy var mapView : MKMapView = {
let mapView = MKMapView(frame: self.view.frame)
mapView.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
mapView.autoresizingMask = UIViewAutoresizing.FlexibleHeight | UIViewAutoresizing.FlexibleWidth
return mapView
}()
+2 -2
View File
@@ -15,11 +15,11 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<string>3.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<string>3.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
@@ -48,7 +48,7 @@ class MultivaluedFormViewController : XLFormViewController {
// Multivalued section
section = XLFormSectionDescriptor.formSectionWithTitle("Multivalued TextField", sectionOptions:XLFormSectionOptions.CanReorder | XLFormSectionOptions.CanInsert | XLFormSectionOptions.CanDelete, sectionInsertMode:XLFormSectionInsertMode.Button)
section.multivaluedAddButton.title = "Add New Tag"
section.multivaluedAddButton!.title = "Add New Tag"
section.footerTitle = "XLFormSectionInsertModeButton sectionType adds a 'Add Item' (Add New Tag) button row as last cell."
// set up the row template
row = XLFormRowDescriptor(tag: nil, rowType: XLFormRowDescriptorTypeName)
@@ -71,12 +71,12 @@ class MultivaluedFormViewController : XLFormViewController {
// Another one
section = XLFormSectionDescriptor.formSectionWithTitle("Multivalued Push Selector example", sectionOptions:XLFormSectionOptions.CanInsert | XLFormSectionOptions.CanDelete | XLFormSectionOptions.CanReorder, sectionInsertMode:XLFormSectionInsertMode.Button)
section = XLFormSectionDescriptor.formSectionWithTitle("Multivalued Push Selector example", sectionOptions: XLFormSectionOptions.CanInsert | XLFormSectionOptions.CanDelete | XLFormSectionOptions.CanReorder, sectionInsertMode:XLFormSectionInsertMode.Button)
section.footerTitle = "MultivaluedFormViewController.swift"
form.addFormSection(section)
row = XLFormRowDescriptor(tag: nil, rowType: XLFormRowDescriptorTypeSelectorPush, title: "Tap to select )..")
row.selectorOptions = ["Option 1", "Option 2", "Option 3"]
section.multivaluedRowTemplate = row.copy() as! XLFormRowDescriptor
section.multivaluedRowTemplate = row.copy() as? XLFormRowDescriptor
section.addFormRow(row)
self.form = form
@@ -267,7 +267,7 @@ class MultivaluedOnlyDeleteViewController : XLFormViewController {
form = XLFormDescriptor(title: "Multivalued Only Delete")
section = XLFormSectionDescriptor.formSectionWithTitle(nil, sectionOptions:XLFormSectionOptions.CanDelete)
section = XLFormSectionDescriptor.formSectionWithTitle("", sectionOptions:XLFormSectionOptions.CanDelete)
section.footerTitle = "you can swipe to delete when table.editing = NO (Not Editing)"
form.addFormSection(section)
@@ -280,7 +280,7 @@ class MultivaluedOnlyDeleteViewController : XLFormViewController {
}
// Multivalued Section with inline row.
section = XLFormSectionDescriptor.formSectionWithTitle(nil, sectionOptions:XLFormSectionOptions.CanDelete)
section = XLFormSectionDescriptor.formSectionWithTitle("", sectionOptions:XLFormSectionOptions.CanDelete)
section.footerTitle = "you can swipe to delete when table.editing = NO (Not Editing)"
form.addFormSection(section)
@@ -115,7 +115,7 @@ class OthersFormViewController : XLFormViewController {
row.cellConfig["textLabel.textAlignment"] = NSTextAlignment.Left.rawValue
row.cellConfig["accessoryType"] = UITableViewCellAccessoryType.DisclosureIndicator.rawValue
row.action.formBlock = { (sender: XLFormRowDescriptor!) -> Void in
let switchRow = sender.sectionDescriptor.formDescriptor.formRowWithTag(Tags.SwitchBool.rawValue)
let switchRow = sender.sectionDescriptor.formDescriptor!.formRowWithTag(Tags.SwitchBool.rawValue)!
if switchRow.value != nil && switchRow.value!.boolValue == true {
let alertView = UIAlertView(title: "Switch is ON", message: "Button has checked the switch value...", delegate: self, cancelButtonTitle: "OK")
alertView.show()
@@ -157,7 +157,7 @@ class OthersFormViewController : XLFormViewController {
func didTouchButton(sender: XLFormRowDescriptor) {
if sender.sectionDescriptor.formDescriptor.formRowWithTag(Tags.SwitchBool.rawValue).value.boolValue == true{
if sender.sectionDescriptor.formDescriptor.formRowWithTag(Tags.SwitchBool.rawValue)?.value?.boolValue == true{
let alertView = UIAlertView(title: "Switch is ON", message: "Button has checked the switch value...", delegate: self, cancelButtonTitle: "OK")
alertView.show()
}
@@ -31,6 +31,7 @@ class BasicPredicateViewController : XLFormViewController {
case HideRow = "tag1"
case HideSection = "tag2"
case Text = "tag3"
case Date = "tag4"
}
@@ -51,18 +52,19 @@ class BasicPredicateViewController : XLFormViewController {
var row : XLFormRowDescriptor
form = XLFormDescriptor(title: "Basic Predicates")
self.form = form
section = XLFormSectionDescriptor()
section.title = "A Section"
form.addFormSection(section)
row = XLFormRowDescriptor(tag: Tags.HideRow.rawValue, rowType: XLFormRowDescriptorTypeBooleanSwitch, title: "Show next row")
row.value = 0
row.value = 1
section.addFormRow(row)
row = XLFormRowDescriptor(tag: Tags.HideSection.rawValue, rowType: XLFormRowDescriptorTypeBooleanSwitch, title: "Show B Section")
row.hidden = "$\(Tags.HideRow.rawValue)==0"
row.value = 0
row.value = 1
section.addFormRow(row)
section = XLFormSectionDescriptor()
@@ -71,11 +73,15 @@ class BasicPredicateViewController : XLFormViewController {
section.hidden = "$\(Tags.HideSection.rawValue)==0"
form.addFormSection(section)
row = XLFormRowDescriptor(tag: Tags.Text.rawValue, rowType: XLFormRowDescriptorTypeText, title:nil)
row = XLFormRowDescriptor(tag: Tags.Text.rawValue, rowType: XLFormRowDescriptorTypeText)
row.cellConfigAtConfigure["textField.placeholder"] = "Gonna disappear soon!!"
section.addFormRow(row)
self.form = form
row = XLFormRowDescriptor(tag: Tags.Date.rawValue, rowType: XLFormRowDescriptorTypeDateInline, title: "Some Date")
row.hidden = "$\(Tags.Text.rawValue).value contains 'aaa'"
section.addFormRow(row)
}
@@ -153,7 +153,7 @@ class NativeEventFormViewController : XLFormViewController {
override func formRowDescriptorValueHasChanged(formRow: XLFormRowDescriptor!, oldValue: AnyObject!, newValue: AnyObject!) {
super.formRowDescriptorValueHasChanged(formRow, oldValue: oldValue, newValue: newValue)
if formRow.tag == "alert" {
if !formRow.value.valueData().isEqual(0) && oldValue.valueData().isEqual(0) {
if !formRow.value!.valueData().isEqual(0) && oldValue.valueData().isEqual(0) {
let newRow = formRow.copy() as! XLFormRowDescriptor
newRow.tag = "secondAlert"
@@ -165,11 +165,11 @@ class NativeEventFormViewController : XLFormViewController {
}
}
else if formRow.tag == "all-day" {
let startDateDescriptor = self.form.formRowWithTag("starts")
let endDateDescriptor = self.form.formRowWithTag("ends")
let dateStartCell: XLFormDateCell = self.form.formRowWithTag("starts").cellForFormController(self) as! XLFormDateCell
let dateEndCell: XLFormDateCell = self.form.formRowWithTag("ends").cellForFormController(self) as! XLFormDateCell
if formRow.value.valueData() as? Bool == true {
let startDateDescriptor = self.form.formRowWithTag("starts")!
let endDateDescriptor = self.form.formRowWithTag("ends")!
let dateStartCell: XLFormDateCell = startDateDescriptor.cellForFormController(self) as! XLFormDateCell
let dateEndCell: XLFormDateCell = endDateDescriptor.cellForFormController(self) as! XLFormDateCell
if formRow.value!.valueData() as? Bool == true {
startDateDescriptor.valueTransformer = DateValueTrasformer.self
endDateDescriptor.valueTransformer = DateValueTrasformer.self
dateStartCell.formDatePickerMode = XLFormDateDatePickerMode.Date
@@ -185,11 +185,11 @@ class NativeEventFormViewController : XLFormViewController {
self.updateFormRow(endDateDescriptor)
}
else if formRow.tag == "starts" {
let startDateDescriptor = self.form.formRowWithTag("starts")
let endDateDescriptor = self.form.formRowWithTag("ends")
let dateStartCell: XLFormDateCell = self.form.formRowWithTag("starts").cellForFormController(self) as! XLFormDateCell
let dateEndCell: XLFormDateCell = self.form.formRowWithTag("ends").cellForFormController(self) as! XLFormDateCell
if startDateDescriptor.value.compare(endDateDescriptor.value as! NSDate) == NSComparisonResult.OrderedDescending {
let startDateDescriptor = self.form.formRowWithTag("starts")!
let endDateDescriptor = self.form.formRowWithTag("ends")!
let dateStartCell: XLFormDateCell = startDateDescriptor.cellForFormController(self) as! XLFormDateCell
let dateEndCell: XLFormDateCell = endDateDescriptor.cellForFormController(self) as! XLFormDateCell
if startDateDescriptor.value!.compare(endDateDescriptor.value as! NSDate) == NSComparisonResult.OrderedDescending {
// startDateDescriptor is later than endDateDescriptor
endDateDescriptor.value = NSDate(timeInterval: 60*60*24, sinceDate: startDateDescriptor.value as! NSDate)
endDateDescriptor.cellConfig.removeObjectForKey("detailTextLabel.attributedText")
@@ -197,10 +197,10 @@ class NativeEventFormViewController : XLFormViewController {
}
}
else if formRow.tag == "ends" {
let startDateDescriptor = self.form.formRowWithTag("starts")
let endDateDescriptor = self.form.formRowWithTag("ends")
let startDateDescriptor = self.form.formRowWithTag("starts")!
let endDateDescriptor = self.form.formRowWithTag("ends")!
let dateEndCell = endDateDescriptor.cellForFormController(self) as! XLFormDateCell
if startDateDescriptor.value.compare(endDateDescriptor.value as! NSDate) == NSComparisonResult.OrderedDescending {
if startDateDescriptor.value!.compare(endDateDescriptor.value as! NSDate) == NSComparisonResult.OrderedDescending {
// startDateDescriptor is later than endDateDescriptor
dateEndCell.update()
let newDetailText : String = dateEndCell.detailTextLabel!.text!
@@ -210,7 +210,7 @@ class NativeEventFormViewController : XLFormViewController {
self.updateFormRow(endDateDescriptor)
}
else{
let endDateDescriptor = self.form.formRowWithTag("ends")
let endDateDescriptor = self.form.formRowWithTag("ends")!
endDateDescriptor.cellConfig.removeObjectForKey("detailTextLabel.attributedText")
self.updateFormRow(endDateDescriptor)
}
@@ -94,7 +94,7 @@ class ValidationExamplesFormViewController : XLFormViewController {
section = XLFormSectionDescriptor()
section.title = "Validation Numbers"
section.footerTitle = "grather than 50 and less than 100"
section.footerTitle = "greater than 50 and less than 100"
form.addFormSection(section)
// Integer
@@ -102,7 +102,7 @@ class ValidationExamplesFormViewController : XLFormViewController {
row.cellConfigAtConfigure["textField.placeholder"] = "Required..."
row.cellConfigAtConfigure["textField.textAlignment"] = NSTextAlignment.Right.rawValue
row.required = true
row.addValidator(XLFormRegexValidator(msg: "grather than 50 and less than 100", andRegexString: "^([5-9][0-9]|100)$"))
row.addValidator(XLFormRegexValidator(msg: "greater than 50 and less than 100", andRegexString: "^([5-9][0-9]|100)$"))
section.addFormRow(row)
self.form = form
@@ -125,18 +125,18 @@ class ValidationExamplesFormViewController : XLFormViewController {
for errorItem in array {
let error = errorItem as! NSError
let validationStatus : XLFormValidationStatus = error.userInfo![XLValidationStatusErrorKey] as! XLFormValidationStatus
if validationStatus.rowDescriptor.tag == Tags.ValidationName.rawValue {
if let cell = self.tableView.cellForRowAtIndexPath(self.form.indexPathOfFormRow(validationStatus.rowDescriptor)) {
if validationStatus.rowDescriptor!.tag == Tags.ValidationName.rawValue {
if let cell = self.tableView.cellForRowAtIndexPath(self.form.indexPathOfFormRow(validationStatus.rowDescriptor)!) {
cell.backgroundColor = UIColor.orangeColor()
UIView.animateWithDuration(0.3, animations: { () -> Void in
cell.backgroundColor = UIColor.whiteColor()
})
}
}
else if validationStatus.rowDescriptor.tag == Tags.ValidationEmail.rawValue ||
validationStatus.rowDescriptor.tag == Tags.ValidationPassword.rawValue ||
validationStatus.rowDescriptor.tag == Tags.ValidationInteger.rawValue {
if let cell = self.tableView.cellForRowAtIndexPath(self.form.indexPathOfFormRow(validationStatus.rowDescriptor)) {
else if validationStatus.rowDescriptor!.tag == Tags.ValidationEmail.rawValue ||
validationStatus.rowDescriptor!.tag == Tags.ValidationPassword.rawValue ||
validationStatus.rowDescriptor!.tag == Tags.ValidationInteger.rawValue {
if let cell = self.tableView.cellForRowAtIndexPath(self.form.indexPathOfFormRow(validationStatus.rowDescriptor)!) {
self.animateCell(cell)
}
}
+89 -16
View File
@@ -4,13 +4,14 @@ XLForm
By [XMARTLABS](http://xmartlabs.com).
[![Build Status](https://travis-ci.org/xmartlabs/XLForm.svg?branch=master)](https://travis-ci.org/xmartlabs/XLForm)
[![license](https://img.shields.io/badge/pod-3.0.2-blue.svg)](https://github.com/xmartlabs/XLForm/releases)
Purpose
--------------
XLForm is the most flexible and powerful iOS library to create dynamic table-view forms. The goal of the library is to get the same power of hand-made forms but spending 1/10 of the time.
XLForm provides a very powerful DSL used to create a form. It keeps track of this specification on runtime, updating the UI on the fly.
XLForm provides a very powerful DSL (Domain Specific Language) used to create a form. It keeps track of this specification on runtime, updating the UI on the fly.
#####Let's see the iOS Calendar Event Form created using XLForm
@@ -23,7 +24,7 @@ What XLForm does
* Loads a form based on a declarative [*form definition*](#how-to-create-a-form "form definition").
* Keeps track of definition changes on runtime to update the form interface accordingly. Further information on [*Dynamic Forms*](#dynamic-forms---how-to-change-the-form-dynamically-at-runtime "Dynamic Forms") section of this readme.
* Supports multivalued sections allowing us to create, delete or reorder rows. For further details see [*Multivalued Sections*](#multivalued-sections "Multivalued Sections") section bellow.
* Supports multivalued sections allowing us to create, delete or reorder rows. For further details see [*Multivalued Sections*](#multivalued-sections-insert-delete-reorder-rows "Multivalued Sections") section bellow.
* Supports [*custom rows definition*](#how-to-create-a-custom-row).
* 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.
@@ -325,27 +326,27 @@ static let time = "time"
var form : XLFormDescriptor
var section : XLFormSectionDescriptor
var row : XLFormRowDescriptor
form = XLFormDescriptor(title: "Dates") as XLFormDescriptor
section = XLFormSectionDescriptor.formSectionWithTitle("Inline Dates") as XLFormSectionDescriptor
form.addFormSection(section)
// Date
row = XLFormRowDescriptor(tag: tag.date, rowType: XLFormRowDescriptorTypeDateInline, title:"Date")
row.value = NSDate()
section.addFormRow(row)
// Time
row = XLFormRowDescriptor(tag: tag.time, rowType: XLFormRowDescriptorTypeTimeInline, title: "Time")
row.value = NSDate()
section.addFormRow(row)
// DateTime
row = XLFormRowDescriptor(tag: tag.dateTime, rowType: XLFormRowDescriptorTypeDateTimeInline, title: "Date Time")
row.value = NSDate()
section.addFormRow(row)
self.form = form;
```
@@ -379,6 +380,18 @@ XLForms supports counting using UIStepper control:
```objc
static NSString *const XLFormRowDescriptorTypeStepCounter = @"stepCounter";
```
You can set the stepper paramaters easily:
```objc
row = [XLFormRowDescriptor formRowDescriptorWithTag:kStepCounter rowType:XLFormRowDescriptorTypeStepCounter title:@"Step counter"];
row.value = @50;
[row.cellConfigAtConfigure setObject:@YES forKey:@"stepControl.wraps"];
[row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.stepValue"];
[row.cellConfigAtConfigure setObject:@10 forKey:@"stepControl.minimumValue"];
[row.cellConfigAtConfigure setObject:@100 forKey:@"stepControl.maximumValue"];
```
#####Slider
XLForms supports counting using UISlider control:
@@ -687,7 +700,7 @@ To make the appearance and disappearance of rows and sections automatic, there i
@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.
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 syntactically 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".
@@ -873,6 +886,19 @@ if let fullName = form.formRowWithTag(tag.fullName).value as? String {
}
```
#### How to change UITextField length
You can change the length of a UITextField using the `cellConfigAtConfigure` dictionary property. This value refers to the percentage in relation to the table view cell.
**Objective C**
```objc
[row.cellConfigAtConfigure setObject:[NSNumber numberWithFloat:0.7] forKey:XLFormTextFieldLengthPercentage];
```
**Swift**
```Swift
row.cellConfigAtConfigure.setObject(0.7, forKey:XLFormTextFieldLengthPercentage)
```
#### How to change a UITableViewCell font
You can change the font or any other table view cell property using the `cellConfig` dictionary property. XLForm will set up `cellConfig` dictionary values when the table view cell is about to be displayed.
@@ -902,19 +928,19 @@ Each XLFormDateCell has a `minimumDate` and a `maximumDate` property. To set a d
```objc
[row.cellConfigAtConfigure setObject:[NSDate new] forKey:@"minimumDate"];
[row.cellConfigAtConfigure setObject:[NSDate dateWithTimeIntervalSinceNow:(60*60*24*3)] forKey:@"maximumDate"];
```
```
**Swift**
```Swift
row.cellConfig.setObject(NSDate(), forKey: "maximumDate")
```
```
####How to disable the entire form (read only mode).
#### 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] ).
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.
#### 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
@@ -922,13 +948,37 @@ 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?
#### 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;
```
#### How to change input accessory view (navigation view)
Overriding `inputAccessoryViewForRowDescriptor:` `XLFormViewController` method.
If you want to disable it completely you can return nil. But you can also customize its whole appearance here.
```obj-c
- (UIView *)inputAccessoryViewForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor
{
return nil; //will hide it completely
// You can use the rowDescriptor parameter to hide/customize the accessory view for a particular rowDescriptor type.
}
```
#### How to set up a pushed view controller?
The view controller that will be pushed must conform to the `XLFormRowDescriptorViewController` protocol which consists of the following property:
```objc
@property (nonatomic) XLFormRowDescriptor * rowDescriptor;
```
This rowDescriptor refers to the selected row of the previous view controller and will be set before the transition to the new controller so that it will be accessible for example in its `viewDidLoad` method. That is where that view controller should be set up.
#### How to change the default appearance of a certain cell
The best way to do this is to extend the class of that cell and override its update and/or configure methods. To make this work you should also update the `cellClassesForRowDescriptorTypes` dictionary in your subclass of XLFormViewController by setting your custom class instead of the class of the cell you wanted to change.
Installation
--------------------------
@@ -936,7 +986,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', '~> 3.0.0'`.
`pod 'XLForm', '~> 3.0'`.
2. Run the command `pod install` from the Podfile folder directory.
XLForm **has no** dependencies over other pods.
@@ -966,12 +1016,35 @@ Requirements
* ARC
* iOS 7.0 and above
* XCode 6.3+
Release Notes
--------------
Version 3.0.0 (master)
Version 3.0.2
* Fix issue when inline pickers expand beyond table.
Version 3.0.1
* Improvements and bug fixes.
* Ability to left, right align textfields. Ability to set up a minimum textField width.
* If form is being shown, assigning a new form automatically reload the tableview.
* Update objective-c and swift example projects.
* Swift compatibility fixes.
* Long email validation added.
* Fixed row copy issue, now valueTransformer value is copied.
* Fixed step counter row layout issues.
* Fixed issue "Last form field hides beneath enabled navigation controller's toolbar".
* Fixed issue "Navigating between cells using bottom navigation buttons causes table cell dividers to disappear".
* Use UIAlertController instead UIActionSheet/UIAlertView if possible.
* Hidden and disabled rows resign first responder before changing state.
* onChangeBlock added to rowDescriptor.
* use tintColor as default button row color.
* By default accessoryView is no longer shown for inline rows.
* Fix NSBundle issues to use XLForm as dynamic framework.
Version 3.0.0
* `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.
+2 -2
View File
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'XLForm'
s.version = '3.0.0'
s.version = '3.0.2'
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 => 'v3.0.0' }
s.source = { :git => 'https://github.com/xmartlabs/XLForm.git', :tag => 'v3.0.2' }
s.source_files = 'XLForm/XL/**/*.{h,m}'
s.requires_arc = true
s.ios.deployment_target = '7.0'
+10 -1
View File
@@ -48,9 +48,18 @@
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;
if (!leftAligmnment){
CGFloat red, green, blue, alpha;
[self.tintColor getRed:&red green:&green blue:&blue alpha:&alpha];
self.textLabel.textColor = [UIColor colorWithRed:red green:green blue:blue alpha:(isDisabled ? 0.3 : 1.0)];
}
else{
self.textLabel.textColor = nil;
}
}
+4
View File
@@ -59,6 +59,9 @@
-(BOOL)becomeFirstResponder
{
if (self.isFirstResponder){
return [super becomeFirstResponder];
}
_beforeChangeColor = self.detailTextLabel.textColor;
BOOL result = [super becomeFirstResponder];
if (result){
@@ -78,6 +81,7 @@
inlineCell.inlineRowDescriptor = self.rowDescriptor;
[formSection addFormRow:datePickerRowDescriptor afterRow:self.rowDescriptor];
[self.formViewController ensureRowIsVisible:datePickerRowDescriptor];
}
}
return result;
@@ -42,6 +42,9 @@
-(BOOL)becomeFirstResponder
{
if (self.isFirstResponder){
return [super becomeFirstResponder];
}
_beforeChangeColor = self.detailTextLabel.textColor;
BOOL result = [super becomeFirstResponder];
if (result){
@@ -51,6 +54,7 @@
UITableViewCell<XLFormInlineRowDescriptorCell> * inlineCell = (UITableViewCell<XLFormInlineRowDescriptorCell> *)cell;
inlineCell.inlineRowDescriptor = self.rowDescriptor;
[self.rowDescriptor.sectionDescriptor addFormRow:inlineRowDescriptor afterRow:self.rowDescriptor];
[self.formViewController ensureRowIsVisible:inlineRowDescriptor];
}
return result;
}
+48 -2
View File
@@ -182,15 +182,59 @@
-(void)leftButtonPressed:(UIButton *)leftButton
{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
actionSheet.tag = [self.rowDescriptor hash];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (XLFormLeftRightSelectorOption * leftOption in self.rowDescriptor.selectorOptions) {
[actionSheet addButtonWithTitle:[leftOption.leftValue displayText]];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
actionSheet.tag = [self.rowDescriptor hash];
[actionSheet showInView:self.formViewController.view];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:self.rowDescriptor.selectorTitle
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
__weak __typeof(self)weakSelf = self;
for (XLFormLeftRightSelectorOption * leftOption in self.rowDescriptor.selectorOptions) {
[alertController addAction:[UIAlertAction actionWithTitle:[leftOption.leftValue displayText]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
weakSelf.rowDescriptor.value = nil;
weakSelf.rowDescriptor.leftRightSelectorLeftOptionSelected = [self leftOptionForDescription:[leftOption.leftValue displayText]].leftValue;
[weakSelf.formViewController updateFormRow:weakSelf.rowDescriptor];
}]];
}
[self.formViewController presentViewController:alertController animated:YES completion:nil];
}
else{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (XLFormLeftRightSelectorOption * leftOption in self.rowDescriptor.selectorOptions) {
[actionSheet addButtonWithTitle:[leftOption.leftValue displayText]];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
actionSheet.tag = [self.rowDescriptor hash];
[actionSheet showInView:self.formViewController.view];
}
#endif
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
@@ -205,5 +249,7 @@
}
}
#endif
@end
+88 -4
View File
@@ -233,23 +233,103 @@
}
}
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorActionSheet]){
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle delegate:self cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil];
actionSheet.tag = [self.rowDescriptor hash];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (id option in self.rowDescriptor.selectorOptions) {
[actionSheet addButtonWithTitle:[option displayText]];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
actionSheet.tag = [self.rowDescriptor hash];
[actionSheet showInView:controller.view];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:self.rowDescriptor.selectorTitle
message:nil
preferredStyle:UIAlertControllerStyleActionSheet];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel"
style:UIAlertActionStyleCancel
handler:nil]];
__weak __typeof(self)weakSelf = self;
for (id option in self.rowDescriptor.selectorOptions) {
[alertController addAction:[UIAlertAction actionWithTitle:[option displayText]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[weakSelf.rowDescriptor setValue:option];
[weakSelf.formViewController.tableView reloadData];
}]];
}
[self.formViewController presentViewController:alertController animated:YES completion:nil];
}
else{
UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:self.rowDescriptor.selectorTitle
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
for (id option in self.rowDescriptor.selectorOptions) {
[actionSheet addButtonWithTitle:[option displayText]];
}
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
actionSheet.tag = [self.rowDescriptor hash];
[actionSheet showInView:controller.view];
}
#endif
[controller.tableView deselectRowAtIndexPath:[controller.form indexPathOfFormRow:self.rowDescriptor] animated:YES];
}
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorAlertView]){
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:self.rowDescriptor.selectorTitle message:nil delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
alertView.tag = [self.rowDescriptor hash];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:self.rowDescriptor.selectorTitle
message:nil
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
for (id option in self.rowDescriptor.selectorOptions) {
[alertView addButtonWithTitle:[option displayText]];
}
alertView.cancelButtonIndex = [alertView addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
alertView.tag = [self.rowDescriptor hash];
[alertView show];
#else
if ([UIAlertController class]) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:self.rowDescriptor.selectorTitle
message:nil
preferredStyle:UIAlertControllerStyleAlert];
__weak __typeof(self)weakSelf = self;
for (id option in self.rowDescriptor.selectorOptions) {
[alertController addAction:[UIAlertAction actionWithTitle:[option displayText]
style:UIAlertActionStyleDefault
handler:^(UIAlertAction *action) {
[weakSelf.rowDescriptor setValue:option];
[weakSelf.formViewController.tableView reloadData];
}]];
}
[alertController addAction:[UIAlertAction actionWithTitle:NSLocalizedString(@"Cancel", nil)
style:UIAlertActionStyleCancel
handler:nil]];
[controller presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:self.rowDescriptor.selectorTitle
message:nil
delegate:self
cancelButtonTitle:nil
otherButtonTitles:nil];
for (id option in self.rowDescriptor.selectorOptions) {
[alertView addButtonWithTitle:[option displayText]];
}
alertView.cancelButtonIndex = [alertView addButtonWithTitle:NSLocalizedString(@"Cancel", nil)];
alertView.tag = [self.rowDescriptor hash];
[alertView show];
}
#endif
[controller.tableView deselectRowAtIndexPath:[controller.form indexPathOfFormRow:self.rowDescriptor] animated:YES];
}
else if ([self.rowDescriptor.rowType isEqualToString:XLFormRowDescriptorTypeSelectorPickerView]){
@@ -270,6 +350,8 @@
self.detailTextLabel.textColor = _beforeChangeColor;
}
#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
#pragma mark - UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
@@ -307,6 +389,8 @@
}
}
#endif
#pragma mark - UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
+38 -43
View File
@@ -26,14 +26,20 @@
#import "XLFormStepCounterCell.h"
#import "XLFormRowDescriptor.h"
#import "UIView+XLFormAdditions.h"
@interface XLFormStepCounterCell ()
@property (nonatomic) UIStepper *stepControl;
@property (nonatomic) UILabel *currentStepValue;
@end
@implementation XLFormStepCounterCell
#pragma mark - XLFormStepCounterCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
@@ -46,27 +52,16 @@
{
[super configure];
self.selectionStyle = UITableViewCellSelectionStyleNone;
UIStepper *stepperControl = [[UIStepper alloc] initWithFrame:CGRectMake(25,
0,
0,
0)];
[stepperControl addTarget:self action:@selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
UILabel *currentStepValue = [[UILabel alloc] initWithFrame:CGRectMake(0,
0,
25,
CGRectGetHeight(stepperControl.frame))];
currentStepValue.textAlignment = NSTextAlignmentCenter;
UIView *container = [[UIView alloc] initWithFrame:CGRectMake(0,
0,
CGRectGetWidth(stepperControl.frame) + CGRectGetWidth(currentStepValue.frame),
CGRectGetHeight(stepperControl.frame))];
[container addSubview:stepperControl];
[container addSubview:currentStepValue];
// Add subviews
[self.contentView addSubview:self.stepControl];
[self.contentView addSubview:self.currentStepValue];
self.accessoryView = container;
self.editingAccessoryView = container;
// Add constraints
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.stepControl attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.currentStepValue attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.contentView attribute:NSLayoutAttributeCenterY multiplier:1 constant:0]];
[self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.currentStepValue attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:self.stepControl attribute:NSLayoutAttributeHeight multiplier:1 constant:0]];
[self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[value]-5-[control]-15-|" options:0 metrics:0 views:@{@"value": self.currentStepValue, @"control":self.stepControl}]];
}
- (void)update
@@ -74,6 +69,7 @@
[super update];
self.textLabel.text = self.rowDescriptor.title;
self.stepControl.value = [self.rowDescriptor.value doubleValue];
self.currentStepValue.text = self.rowDescriptor.value ? [NSString stringWithFormat:@"%@", self.rowDescriptor.value] : nil;
[self stepControl].enabled = !self.rowDescriptor.isDisabled;
[self currentStepValue].font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
CGFloat red, green, blue, alpha;
@@ -87,40 +83,39 @@
[self setTintColor:[UIColor colorWithRed:red green:green blue:blue alpha:1]];
[self currentStepValue].textColor = [UIColor colorWithRed:red green:green blue:blue alpha:1];
}
[self valueChanged:nil];
}
- (UIStepper *)stepControl
{
for (UIView *view in self.accessoryView.subviews) {
if ([view isMemberOfClass:[UIStepper class]]) {
return (UIStepper *)view;
}
}
return nil;
}
- (UILabel *)currentStepValue
{
for (UIView *view in self.accessoryView.subviews) {
if ([view isMemberOfClass:[UILabel class]]) {
return (UILabel *)view;
}
}
return nil;
}
#pragma mark - Events
- (void)valueChanged:(id)sender
{
UIStepper *stepper = self.stepControl;
self.rowDescriptor.value = stepper.value == 0 ? nil : @(stepper.value);
self.currentStepValue.text = stepper.value == 0 ? nil : [NSString stringWithFormat:@"%.f", stepper.value];
self.rowDescriptor.value = @(stepper.value);
self.currentStepValue.text = [NSString stringWithFormat:@"%.f", stepper.value];
}
#pragma mark - Properties
- (UIStepper *)stepControl
{
if (!_stepControl) {
_stepControl = [UIStepper autolayoutView];
[_stepControl addTarget:self action:@selector(valueChanged:) forControlEvents:UIControlEventValueChanged];
}
return _stepControl;
}
-(UILabel *)currentStepValue
{
if (!_currentStepValue) {
_currentStepValue = [UILabel autolayoutView];
}
return _currentStepValue;
}
@end
+4 -1
View File
@@ -24,12 +24,15 @@
// THE SOFTWARE.
#import "XLFormBaseCell.h"
#import <UIKit/UIKit.h>
extern NSString *const XLFormTextFieldLengthPercentage;
@interface XLFormTextFieldCell : XLFormBaseCell
@property (nonatomic, readonly) UILabel * textLabel;
@property (nonatomic, readonly) UITextField * textField;
@property (nonatomic) NSNumber *textFieldLengthPercentage;
@end
+19 -6
View File
@@ -29,9 +29,11 @@
#import "XLForm.h"
#import "XLFormTextFieldCell.h"
NSString *const XLFormTextFieldLengthPercentage = @"textFieldLengthPercentage";
@interface XLFormTextFieldCell() <UITextFieldDelegate>
@property NSArray * dynamicCustomConstraints;
@property NSMutableArray * dynamicCustomConstraints;
@property UIReturnKeyType returnKeyType;
@end
@@ -182,9 +184,11 @@
NSMutableArray * result = [[NSMutableArray alloc] init];
[self.textLabel setContentHuggingPriority:500 forAxis:UILayoutConstraintAxisHorizontal];
[self.textLabel setContentCompressionResistancePriority:1000 forAxis:UILayoutConstraintAxisHorizontal];
[result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=11)-[_textField]-(>=11)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:NSDictionaryOfVariableBindings(_textField)]];
// Add Constraints
[result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=11)-[_textField]-(>=11)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:NSDictionaryOfVariableBindings(_textField)]];
[result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(>=11)-[_textLabel]-(>=11)-|" options:NSLayoutFormatAlignAllBaseline metrics:nil views:NSDictionaryOfVariableBindings(_textLabel)]];
return result;
}
@@ -198,20 +202,29 @@
if (self.imageView.image){
if (self.textLabel.text.length > 0){
self.dynamicCustomConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[image]-[label]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views];
self.dynamicCustomConstraints = [NSMutableArray arrayWithArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[image]-[label]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views]];
}
else{
self.dynamicCustomConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:[image]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views];
self.dynamicCustomConstraints = [NSMutableArray arrayWithArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[image]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views]];
}
}
else{
if (self.textLabel.text.length > 0){
self.dynamicCustomConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(leftMargin)-[label]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views];
self.dynamicCustomConstraints = [NSMutableArray arrayWithArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(leftMargin)-[label]-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views]];
}
else{
self.dynamicCustomConstraints = [NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(leftMargin)-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views];
self.dynamicCustomConstraints = [NSMutableArray arrayWithArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-(leftMargin)-[textField]-(rightMargin)-|" options:0 metrics:metrics views:views]];
}
}
[self.dynamicCustomConstraints addObject:[NSLayoutConstraint constraintWithItem:_textField
attribute:NSLayoutAttributeWidth
relatedBy:self.textFieldLengthPercentage ? NSLayoutRelationEqual : NSLayoutRelationGreaterThanOrEqual
toItem:self.contentView
attribute:NSLayoutAttributeWidth
multiplier:self.textFieldLengthPercentage ? [self.textFieldLengthPercentage floatValue] : 0.3
constant:0.0]];
[self.contentView addConstraints:self.dynamicCustomConstraints];
[super updateConstraints];
}
@@ -74,6 +74,8 @@ typedef NS_ENUM(NSUInteger, XLFormRowNavigationDirection) {
-(void)beginEditing:(XLFormRowDescriptor *)rowDescriptor;
-(void)endEditing:(XLFormRowDescriptor *)rowDescriptor;
-(void)ensureRowIsVisible:(XLFormRowDescriptor *)inlineRowDescriptor;
@end
@interface XLFormViewController : UIViewController<UITableViewDataSource, UITableViewDelegate, XLFormDescriptorDelegate, UITextFieldDelegate, UITextViewDelegate, UIActionSheetDelegate, XLFormViewControllerDelegate>
+70 -15
View File
@@ -53,7 +53,10 @@
@interface XLFormViewController()
{
NSNumber *_oldBottomTableContentInset;
CGRect _keyboardFrame;
}
@property UITableViewStyle tableViewStyle;
@property (nonatomic) XLFormRowNavigationAccessoryView * navigationAccessoryView;
@@ -137,6 +140,7 @@
[self.tableView setEditing:YES animated:NO];
self.tableView.allowsSelectionDuringEditing = YES;
self.form.delegate = self;
_oldBottomTableContentInset = nil;
}
-(void)viewWillAppear:(BOOL)animated
@@ -145,7 +149,8 @@
NSIndexPath *selected = [self.tableView indexPathForSelectedRow];
if (selected){
// Trigger a cell refresh
[self tableView:self.tableView cellForRowAtIndexPath:selected];
XLFormRowDescriptor * rowDescriptor = [self.form formRowAtIndex:selected];
[self updateFormRow:rowDescriptor];
[self.tableView selectRowAtIndexPath:selected animated:NO scrollPosition:UITableViewScrollPositionNone];
[self.tableView deselectRowAtIndexPath:selected animated:YES];
}
@@ -256,7 +261,8 @@
@{XLFormRowDescriptorTypeSelectorPickerViewInline: XLFormRowDescriptorTypePicker,
XLFormRowDescriptorTypeDateInline: XLFormRowDescriptorTypeDatePicker,
XLFormRowDescriptorTypeDateTimeInline: XLFormRowDescriptorTypeDatePicker,
XLFormRowDescriptorTypeTimeInline: XLFormRowDescriptorTypeDatePicker
XLFormRowDescriptorTypeTimeInline: XLFormRowDescriptorTypeDatePicker,
XLFormRowDescriptorTypeCountDownTimerInline: XLFormRowDescriptorTypeDatePicker
} mutableCopy];
});
return _inlineRowDescriptorTypesForRowDescriptorTypes;
@@ -304,7 +310,8 @@
}
}
-(void)updateAfterDependentRowChanged:(XLFormRowDescriptor *)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) {
@@ -383,6 +390,9 @@
if ((self.form.rowNavigationOptions & XLFormRowNavigationOptionEnabled) != XLFormRowNavigationOptionEnabled){
return nil;
}
if ([[[[self class] inlineRowDescriptorTypesForRowDescriptorTypes] allKeys] containsObject:rowDescriptor.rowType]) {
return nil;
}
UITableViewCell<XLFormDescriptorCell> * cell = (UITableViewCell<XLFormDescriptorCell> *)[rowDescriptor cellForFormController:self];
if (![cell formDescriptorCellCanBecomeFirstResponder]){
return nil;
@@ -432,6 +442,15 @@
}
}
-(void)ensureRowIsVisible:(XLFormRowDescriptor *)inlineRowDescriptor
{
XLFormBaseCell * inlineCell = [inlineRowDescriptor cellForFormController:self];
NSIndexPath * indexOfOutOfWindowCell = [self.form indexPathOfFormRow:inlineRowDescriptor];
if(!inlineCell.window || (self.tableView.contentOffset.y + self.tableView.frame.size.height <= inlineCell.frame.origin.y + inlineCell.frame.size.height)){
[self.tableView scrollToRowAtIndexPath:indexOfOutOfWindowCell atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
#pragma mark - Methods
-(NSArray *)formValidationErrors
@@ -441,8 +460,32 @@
-(void)showFormValidationError:(NSError *)error
{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"XLFormViewController_ValidationErrorTitle", nil) message:error.localizedDescription delegate:self cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil];
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"XLFormViewController_ValidationErrorTitle", nil)
message:error.localizedDescription
delegate:self
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[alertView show];
#else
if ([UIAlertController class]){
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:NSLocalizedString(@"XLFormViewController_ValidationErrorTitle", nil)
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction actionWithTitle:@"OK"
style:UIAlertActionStyleDefault
handler:nil]];
[self presentViewController:alertController animated:YES completion:nil];
}
else{
UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"XLFormViewController_ValidationErrorTitle", nil)
message:error.localizedDescription
delegate:self
cancelButtonTitle:NSLocalizedString(@"OK", nil)
otherButtonTitles:nil];
[alertView show];
}
#endif
}
-(void)performFormSelector:(SEL)selector withObject:(id)sender
@@ -469,11 +512,12 @@
UITableViewCell<XLFormDescriptorCell> * cell = [firstResponderView formDescriptorCell];
if (cell){
NSDictionary *keyboardInfo = [notification userInfo];
CGRect keyboardFrame = [self.tableView.window convertRect:[keyboardInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue] toView:self.tableView.superview];
CGFloat newBottomInset = self.tableView.frame.origin.y + self.tableView.frame.size.height - keyboardFrame.origin.y;
if (newBottomInset > 0){
UIEdgeInsets tableContentInset = self.tableView.contentInset;
UIEdgeInsets tableScrollIndicatorInsets = self.tableView.scrollIndicatorInsets;
_keyboardFrame = [self.tableView.window convertRect:[keyboardInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue] toView:self.tableView.superview];
CGFloat newBottomInset = self.tableView.frame.origin.y + self.tableView.frame.size.height - _keyboardFrame.origin.y;
UIEdgeInsets tableContentInset = self.tableView.contentInset;
UIEdgeInsets tableScrollIndicatorInsets = self.tableView.scrollIndicatorInsets;
_oldBottomTableContentInset = _oldBottomTableContentInset ?: @(tableContentInset.bottom);
if (newBottomInset > [_oldBottomTableContentInset floatValue]){
tableContentInset.bottom = newBottomInset;
tableScrollIndicatorInsets.bottom = tableContentInset.bottom;
[UIView beginAnimations:nil context:nil];
@@ -493,11 +537,13 @@
UIView * firstResponderView = [self.tableView findFirstResponder];
UITableViewCell<XLFormDescriptorCell> * cell = [firstResponderView formDescriptorCell];
if (cell){
_keyboardFrame = CGRectZero;
NSDictionary *keyboardInfo = [notification userInfo];
UIEdgeInsets tableContentInset = self.tableView.contentInset;
UIEdgeInsets tableScrollIndicatorInsets = self.tableView.scrollIndicatorInsets;
tableContentInset.bottom = 0;
tableContentInset.bottom = [_oldBottomTableContentInset floatValue];
tableScrollIndicatorInsets.bottom = tableContentInset.bottom;
_oldBottomTableContentInset = nil;
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:[keyboardInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue]];
[UIView setAnimationCurve:[keyboardInfo[UIKeyboardAnimationCurveUserInfoKey] intValue]];
@@ -529,6 +575,7 @@
{
XLFormBaseCell * cell = [formRow cellForFormController:self];
cell.rowDescriptor = formRow;
[cell setNeedsUpdateConstraints];
[cell setNeedsLayout];
return cell;
}
@@ -552,7 +599,13 @@
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
XLFormRowDescriptor * rowDescriptor = [self.form formRowAtIndex:indexPath];
return [self updateFormRow:rowDescriptor];
return [rowDescriptor cellForFormController:self];
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
XLFormRowDescriptor * rowDescriptor = [self.form formRowAtIndex:indexPath];
[self updateFormRow:rowDescriptor];
}
@@ -888,10 +941,7 @@
UITableViewCell<XLFormDescriptorCell> * cell = (UITableViewCell<XLFormDescriptorCell> *)[nextRow cellForFormController:self];
if ([cell formDescriptorCellCanBecomeFirstResponder]){
NSIndexPath * indexPath = [self.form indexPathOfFormRow:nextRow];
[self.tableView beginUpdates];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
[self.tableView endUpdates];
[cell formDescriptorCellBecomeFirstResponder];
}
}
@@ -933,9 +983,14 @@
-(void)setForm:(XLFormDescriptor *)form
{
_form.delegate = nil;
[self.tableView endEditing:YES];
_form = form;
_form.delegate = self;
[_form forceEvaluate];
if ([self isViewLoaded]){
[self.tableView reloadData];
}
}
-(XLFormDescriptor *)form
+28 -29
View File
@@ -28,8 +28,8 @@
#import "XLFormDescriptorDelegate.h"
#import <Foundation/Foundation.h>
extern NSString * const XLFormErrorDomain;
extern NSString * const XLValidationStatusErrorKey;
extern NSString * __nonnull const XLFormErrorDomain;
extern NSString * __nonnull const XLValidationStatusErrorKey;
typedef NS_ENUM(NSInteger, XLFormErrorCode)
{
@@ -49,46 +49,45 @@ typedef NS_OPTIONS(NSUInteger, XLFormRowNavigationOptions) {
@interface XLFormDescriptor : NSObject
@property (readonly, nonatomic) NSMutableArray * formSections;
@property (readonly) NSString * title;
@property (readonly, nonatomic, nonnull) NSMutableArray * formSections;
@property (readonly, nullable) NSString * title;
@property (nonatomic) BOOL assignFirstResponderOnShow;
@property (nonatomic) BOOL addAsteriskToRequiredRowsTitle;
@property (getter=isDisabled) BOOL disabled;
@property (nonatomic) XLFormRowNavigationOptions rowNavigationOptions;
@property (weak) id<XLFormDescriptorDelegate> delegate;
@property (weak, nullable) id<XLFormDescriptorDelegate> delegate;
-(instancetype)initWithTitle:(NSString *)title;
+(instancetype)formDescriptor;
+(instancetype)formDescriptorWithTitle:(NSString *)title;
+(nonnull instancetype)formDescriptor;
+(nonnull instancetype)formDescriptorWithTitle:(nullable NSString *)title;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index;
-(void)addFormSection:(XLFormSectionDescriptor *)formSection afterSection:(XLFormSectionDescriptor *)afterSection;
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRowTag:(NSString *)afterRowTag;
-(void)addFormRow:(XLFormRowDescriptor *)formRow afterRow:(XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(XLFormRowDescriptor *)formRow afterRowTag:(NSString *)afterRowTag;
-(void)addFormSection:(nonnull XLFormSectionDescriptor *)formSection;
-(void)addFormSection:(nonnull XLFormSectionDescriptor *)formSection atIndex:(NSUInteger)index;
-(void)addFormSection:(nonnull XLFormSectionDescriptor *)formSection afterSection:(nonnull XLFormSectionDescriptor *)afterSection;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow beforeRow:(nonnull XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow beforeRowTag:(nonnull NSString *)afterRowTag;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow afterRow:(nonnull XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow afterRowTag:(nonnull NSString *)afterRowTag;
-(void)removeFormSectionAtIndex:(NSUInteger)index;
-(void)removeFormSection:(XLFormSectionDescriptor *)formSection;
-(void)removeFormRow:(XLFormRowDescriptor *)formRow;
-(void)removeFormRowWithTag:(NSString *)tag;
-(void)removeFormSection:(nonnull XLFormSectionDescriptor *)formSection;
-(void)removeFormRow:(nonnull XLFormRowDescriptor *)formRow;
-(void)removeFormRowWithTag:(nonnull NSString *)tag;
-(XLFormRowDescriptor *)formRowWithTag:(NSString *)tag;
-(XLFormRowDescriptor *)formRowAtIndex:(NSIndexPath *)indexPath;
-(XLFormRowDescriptor *)formRowWithHash:(NSUInteger)hash;
-(XLFormSectionDescriptor *)formSectionAtIndex:(NSUInteger)index;
-(nullable XLFormRowDescriptor *)formRowWithTag:(nonnull NSString *)tag;
-(nullable XLFormRowDescriptor *)formRowAtIndex:(nonnull NSIndexPath *)indexPath;
-(nullable XLFormRowDescriptor *)formRowWithHash:(NSUInteger)hash;
-(nullable XLFormSectionDescriptor *)formSectionAtIndex:(NSUInteger)index;
-(NSIndexPath *)indexPathOfFormRow:(XLFormRowDescriptor *)formRow;
-(nullable NSIndexPath *)indexPathOfFormRow:(nonnull XLFormRowDescriptor *)formRow;
-(NSDictionary *)formValues;
-(NSDictionary *)httpParameters:(XLFormViewController *)formViewController;
-(nonnull NSDictionary *)formValues;
-(nonnull NSDictionary *)httpParameters:(nonnull XLFormViewController *)formViewController;
-(NSArray *)localValidationErrors:(XLFormViewController *)formViewController;
- (void)setFirstResponder:(XLFormViewController *)formViewController;
-(nonnull NSArray *)localValidationErrors:(nonnull XLFormViewController *)formViewController;
-(void)setFirstResponder:(nonnull XLFormViewController *)formViewController;
-(XLFormRowDescriptor *)nextRowDescriptorForRow:(XLFormRowDescriptor *)currentRow;
-(XLFormRowDescriptor *)previousRowDescriptorForRow:(XLFormRowDescriptor *)currentRow;
-(nullable XLFormRowDescriptor *)nextRowDescriptorForRow:(nonnull XLFormRowDescriptor *)currentRow;
-(nullable XLFormRowDescriptor *)previousRowDescriptorForRow:(nonnull XLFormRowDescriptor *)currentRow;
-(void)forceEvaluate;
+2 -2
View File
@@ -85,12 +85,12 @@ NSString * const XLValidationStatusErrorKey = @"XLValidationStatusErrorKey";
+(instancetype)formDescriptor
{
return [self formDescriptorWithTitle:nil];
return [[self class] formDescriptorWithTitle:nil];
}
+(instancetype)formDescriptorWithTitle:(NSString *)title
{
return [[XLFormDescriptor alloc] initWithTitle:title];
return [[[self class] alloc] initWithTitle:title];
}
-(void)addFormSection:(XLFormSectionDescriptor *)formSection
+48 -45
View File
@@ -41,56 +41,60 @@ typedef NS_ENUM(NSUInteger, XLFormPresentationMode) {
XLFormPresentationModePresent
};
typedef void(^XLOnChangeBlock)(id __nullable oldValue,id __nullable newValue,XLFormRowDescriptor* __nonnull rowDescriptor);
@interface XLFormRowDescriptor : NSObject
@property id cellClass;
@property (readwrite) NSString *tag;
@property (readonly) NSString *rowType;
@property NSString *title;
@property (nonatomic) id value;
@property Class valueTransformer;
@property (nullable) id cellClass;
@property (readwrite, nullable) NSString * tag;
@property (readonly, nonnull) NSString * rowType;
@property (nullable) NSString * title;
@property (nonatomic, nullable) id value;
@property (nullable) Class valueTransformer;
@property UITableViewCellStyle cellStyle;
@property (nonatomic) NSMutableDictionary *cellConfig;
@property (nonatomic) NSMutableDictionary *cellConfigIfDisabled;
@property (nonatomic) NSMutableDictionary *cellConfigAtConfigure;
@property (copy, nullable) XLOnChangeBlock onChangeBlock;
@property id disabled;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfig;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigIfDisabled;
@property (nonatomic, readonly, nonnull) NSMutableDictionary * cellConfigAtConfigure;
@property (nonnull) id disabled;
-(BOOL)isDisabled;
@property id hidden;
@property (nonnull) id hidden;
-(BOOL)isHidden;
@property (getter=isRequired) BOOL required;
@property XLFormAction * action;
@property (nonnull) XLFormAction * action;
@property (weak) XLFormSectionDescriptor * sectionDescriptor;
@property (weak, null_unspecified) XLFormSectionDescriptor * sectionDescriptor;
+(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType;
+(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title;
+(nonnull instancetype)formRowDescriptorWithTag:(nullable NSString *)tag rowType:(nonnull NSString *)rowType;
+(nonnull instancetype)formRowDescriptorWithTag:(nullable NSString *)tag rowType:(nonnull NSString *)rowType title:(nullable NSString *)title;
-(XLFormBaseCell *)cellForFormController:(XLFormViewController *)formController;
-(nonnull XLFormBaseCell *)cellForFormController:(nonnull XLFormViewController *)formController;
@property NSString *requireMsg;
-(void)addValidator:(id<XLFormValidatorProtocol>)validator;
-(void)removeValidator:(id<XLFormValidatorProtocol>)validator;
-(XLFormValidationStatus *)doValidation;
@property (nullable) NSString *requireMsg;
-(void)addValidator:(nonnull id<XLFormValidatorProtocol>)validator;
-(void)removeValidator:(nonnull id<XLFormValidatorProtocol>)validator;
-(nonnull XLFormValidationStatus *)doValidation;
// ===========================
// property used for Selectors
// ===========================
@property NSString * noValueDisplayText;
@property NSString * selectorTitle;
@property NSArray * selectorOptions;
@property (nullable) NSString * noValueDisplayText;
@property (nullable) NSString * selectorTitle;
@property (nullable) NSArray * selectorOptions;
@property id leftRightSelectorLeftOptionSelected;
@property (null_unspecified) id leftRightSelectorLeftOptionSelected;
// =====================================
// Deprecated
// =====================================
@property Class buttonViewController DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");
@property (null_unspecified) Class buttonViewController DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");
@property XLFormPresentationMode buttonViewControllerPresentationMode DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("use action.viewControllerPresentationMode instead");
@property Class selectorControllerClass DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");
@property (null_unspecified) Class selectorControllerClass DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use action.viewControllerClass instead");
@end
@@ -101,18 +105,18 @@ typedef NS_ENUM(NSUInteger, XLFormPresentationMode) {
// =====================================
@interface XLFormLeftRightSelectorOption : NSObject
@property (readonly) id leftValue;
@property (readonly) NSArray * rightOptions;
@property (readonly) NSString * httpParameterKey;
@property Class rightSelectorControllerClass;
@property (readonly, nonnull) id leftValue;
@property (readonly, nonnull) NSArray * rightOptions;
@property (readonly, null_unspecified) NSString * httpParameterKey;
@property (nullable) Class rightSelectorControllerClass;
@property NSString * noValueDisplayText;
@property NSString * selectorTitle;
@property (nullable) NSString * noValueDisplayText;
@property (nullable) NSString * selectorTitle;
+(XLFormLeftRightSelectorOption *)formLeftRightSelectorOptionWithLeftValue:(id)leftValue
httpParameterKey:(NSString *)httpParameterKey
rightOptions:(NSArray *)rightOptions;
+(nonnull XLFormLeftRightSelectorOption *)formLeftRightSelectorOptionWithLeftValue:(nonnull id)leftValue
httpParameterKey:(null_unspecified NSString *)httpParameterKey
rightOptions:(nonnull NSArray *)rightOptions;
@end
@@ -122,23 +126,22 @@ typedef NS_ENUM(NSUInteger, XLFormPresentationMode) {
@required
-(NSString *)formDisplayText;
-(id)formValue;
-(nonnull NSString *)formDisplayText;
-(nonnull id)formValue;
@end
@interface XLFormAction : NSObject
@property (nonatomic, strong) Class viewControllerClass;
@property (nonatomic, strong) NSString * viewControllerStoryboardId;
@property (nonatomic, strong) NSString * viewControllerNibName;
@property (nullable, nonatomic, strong) Class viewControllerClass;
@property (nullable, nonatomic, strong) NSString * viewControllerStoryboardId;
@property (nullable, nonatomic, strong) NSString * viewControllerNibName;
@property (nonatomic) XLFormPresentationMode viewControllerPresentationMode;
@property (nonatomic, strong) void (^formBlock)(XLFormRowDescriptor * sender);
@property (nonatomic) SEL formSelector;
@property (nonatomic, strong) NSString * formSegueIdenfifier;
@property (nonatomic, strong) Class formSegueClass;
@property (nullable, nonatomic, strong) void (^formBlock)(XLFormRowDescriptor * __nonnull sender);
@property (nullable, nonatomic) SEL formSelector;
@property (nullable, nonatomic, strong) NSString * formSegueIdenfifier;
@property (nullable, nonatomic, strong) Class formSegueClass;
@end
+35 -19
View File
@@ -63,7 +63,9 @@
@synthesize hidden = _hidden;
@synthesize hidePredicateCache = _hidePredicateCache;
@synthesize disablePredicateCache = _disablePredicateCache;
@synthesize cellConfig = _cellConfig;
@synthesize cellConfigIfDisabled = _cellConfigIfDisabled;
@synthesize cellConfigAtConfigure = _cellConfigAtConfigure;
-(instancetype)init
{
@@ -92,18 +94,19 @@
[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;
}
+(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType
{
return [XLFormRowDescriptor formRowDescriptorWithTag:tag rowType:rowType title:nil];
return [[self class] formRowDescriptorWithTag:tag rowType:rowType title:nil];
}
+(instancetype)formRowDescriptorWithTag:(NSString *)tag rowType:(NSString *)rowType title:(NSString *)title
{
return [[XLFormRowDescriptor alloc] initWithTag:tag rowType:rowType title:title];
return [[[self class] alloc] initWithTag:tag rowType:rowType title:title];
}
-(XLFormBaseCell *)cellForFormController:(XLFormViewController *)formController
@@ -112,8 +115,9 @@
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];
NSBundle *bundle = [NSBundle bundleForClass:NSClassFromString(cellClass)];
if ([bundle pathForResource:cellClass ofType:@"nib"]){
_cell = [[bundle loadNibNamed:cellClass owner:nil options:nil] firstObject];
}
} else {
_cell = [[cellClass alloc] initWithStyle:self.cellStyle reuseIdentifier:nil];
@@ -175,29 +179,30 @@
{
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.cellConfig addEntriesFromDictionary:self.cellConfig];
[rowDescriptorCopy.cellConfigAtConfigure addEntriesFromDictionary:self.cellConfigAtConfigure];
rowDescriptorCopy.valueTransformer = [self.valueTransformer copy];
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
// ===========================
rowDescriptorCopy.noValueDisplayText = [self.noValueDisplayText copy];
rowDescriptorCopy.selectorTitle = [self.selectorTitle copy];
rowDescriptorCopy.selectorOptions = [self.selectorOptions copy];
rowDescriptorCopy.leftRightSelectorLeftOptionSelected = [self.leftRightSelectorLeftOptionSelected copy];
return rowDescriptorCopy;
}
@@ -230,6 +235,9 @@
id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
if ([keyPath isEqualToString:@"value"]){
[self.sectionDescriptor.formDescriptor.delegate formRowDescriptorValueHasChanged:object oldValue:oldValue newValue:newValue];
if (self.onChangeBlock) {
self.onChangeBlock(oldValue, newValue, self);
}
}
else{
[self.sectionDescriptor.formDescriptor.delegate formRowDescriptorPredicateHasChanged:object oldValue:oldValue newValue:newValue predicateType:([keyPath isEqualToString:@"hidePredicateCache"] ? XLPredicateTypeHidden : XLPredicateTypeDisabled)];
@@ -260,7 +268,7 @@
if ([_disabled isKindOfClass:[NSPredicate class]]){
[self.sectionDescriptor.formDescriptor addObserversOfObject:self predicateType:XLPredicateTypeDisabled];
}
[self evaluateIsDisabled];
}
@@ -278,6 +286,9 @@
else{
self.disablePredicateCache = _disabled;
}
if ([self.disablePredicateCache boolValue]){
[self.cell resignFirstResponder];
}
return [self.disablePredicateCache boolValue];
}
@@ -338,7 +349,13 @@
else{
self.hidePredicateCache = _hidden;
}
[self.hidePredicateCache boolValue] ? [self.sectionDescriptor hideFormRow:self] : [self.sectionDescriptor showFormRow:self];
if ([self.hidePredicateCache boolValue]){
[self.cell resignFirstResponder];
[self.sectionDescriptor hideFormRow:self];
}
else{
[self.sectionDescriptor showFormRow:self];
}
return [self.hidePredicateCache boolValue];
}
@@ -367,7 +384,7 @@
{
if (validator == nil || ![validator conformsToProtocol:@protocol(XLFormValidatorProtocol)])
return;
if(![self.validators containsObject:validator]) {
[self.validators addObject:validator];
}
@@ -377,7 +394,7 @@
{
if (validator == nil|| ![validator conformsToProtocol:@protocol(XLFormValidatorProtocol)])
return;
if ([self.validators containsObject:validator]) {
[self.validators removeObject:validator];
}
@@ -391,7 +408,7 @@
-(XLFormValidationStatus *)doValidation
{
XLFormValidationStatus *valStatus = nil;
if (self.required) {
// do required validation here
if ([self valueIsEmpty]) {
@@ -403,7 +420,7 @@
// default message for required msg
msg = NSLocalizedString(@"%@ can't be empty", nil);
}
if (self.title != nil) {
valStatus.msg = [NSString stringWithFormat:msg, self.title];
} else {
@@ -590,4 +607,3 @@
}
@end
+17 -17
View File
@@ -42,32 +42,32 @@ typedef NS_ENUM(NSUInteger, XLFormSectionInsertMode) {
@interface XLFormSectionDescriptor : NSObject
@property (nonatomic) NSString * title;
@property (nonatomic) NSString * footerTitle;
@property (readonly) NSMutableArray * formRows;
@property (nonatomic, nullable) NSString * title;
@property (nonatomic, nullable) NSString * footerTitle;
@property (readonly, nonnull) NSMutableArray * formRows;
@property (readonly) XLFormSectionInsertMode sectionInsertMode;
@property (readonly) XLFormSectionOptions sectionOptions;
@property XLFormRowDescriptor * multivaluedRowTemplate;
@property (readonly) XLFormRowDescriptor * multivaluedAddButton;
@property (nonatomic) NSString * multivaluedTag;
@property (nullable) XLFormRowDescriptor * multivaluedRowTemplate;
@property (readonly, nullable) XLFormRowDescriptor * multivaluedAddButton;
@property (nonatomic, nullable) NSString * multivaluedTag;
@property (weak) XLFormDescriptor * formDescriptor;
@property (weak, null_unspecified) XLFormDescriptor * formDescriptor;
@property id hidden;
@property (nonnull) id hidden;
-(BOOL)isHidden;
+(instancetype)formSection;
+(instancetype)formSectionWithTitle:(NSString *)title;
+(instancetype)formSectionWithTitle:(NSString *)title multivaluedSection:(BOOL)multivaluedSection DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use formSectionWithTitle:sectionType: instead");
+(instancetype)formSectionWithTitle:(NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions;
+(instancetype)formSectionWithTitle:(NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions sectionInsertMode:(XLFormSectionInsertMode)sectionInsertMode;
+(nonnull instancetype)formSection;
+(nonnull instancetype)formSectionWithTitle:(nullable NSString *)title;
+(nonnull instancetype)formSectionWithTitle:(nullable NSString *)title multivaluedSection:(BOOL)multivaluedSection DEPRECATED_ATTRIBUTE DEPRECATED_MSG_ATTRIBUTE("Use formSectionWithTitle:sectionType: instead");
+(nonnull instancetype)formSectionWithTitle:(nullable NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions;
+(nonnull instancetype)formSectionWithTitle:(nullable NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions sectionInsertMode:(XLFormSectionInsertMode)sectionInsertMode;
-(BOOL)isMultivaluedSection;
-(void)addFormRow:(XLFormRowDescriptor *)formRow;
-(void)addFormRow:(XLFormRowDescriptor *)formRow afterRow:(XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(XLFormRowDescriptor *)formRow beforeRow:(XLFormRowDescriptor *)beforeRow;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow afterRow:(nonnull XLFormRowDescriptor *)afterRow;
-(void)addFormRow:(nonnull XLFormRowDescriptor *)formRow beforeRow:(nonnull XLFormRowDescriptor *)beforeRow;
-(void)removeFormRowAtIndex:(NSUInteger)index;
-(void)removeFormRow:(XLFormRowDescriptor *)formRow;
-(void)removeFormRow:(nonnull XLFormRowDescriptor *)formRow;
@end
@@ -27,6 +27,7 @@
#import "XLFormSectionDescriptor.h"
#import "NSPredicate+XLFormAdditions.h"
#import "NSString+XLFormAdditions.h"
#import "UIView+XLFormAdditions.h"
@interface XLFormDescriptor (_XLFormSectionDescriptor)
@@ -84,7 +85,6 @@
if ([self canInsertUsingButton]){
_multivaluedAddButton = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeButton title:@"Add Item"];
[_multivaluedAddButton.cellConfig setObject:@(NSTextAlignmentLeft) forKey:@"textLabel.textAlignment"];
[_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];
@@ -95,27 +95,27 @@
+(instancetype)formSection
{
return [self formSectionWithTitle:nil];
return [[self class] formSectionWithTitle:nil];
}
+(instancetype)formSectionWithTitle:(NSString *)title
{
return [self formSectionWithTitle:title sectionOptions:XLFormSectionOptionNone];
return [[self class] formSectionWithTitle:title sectionOptions:XLFormSectionOptionNone];
}
+(instancetype)formSectionWithTitle:(NSString *)title multivaluedSection:(BOOL)multivaluedSection
{
return [self formSectionWithTitle:title sectionOptions:(multivaluedSection ? XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete : XLFormSectionOptionNone)];
return [[self class] formSectionWithTitle:title sectionOptions:(multivaluedSection ? XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete : XLFormSectionOptionNone)];
}
+(instancetype)formSectionWithTitle:(NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions
{
return [self formSectionWithTitle:title sectionOptions:sectionOptions sectionInsertMode:XLFormSectionInsertModeLastRow];
return [[self class] formSectionWithTitle:title sectionOptions:sectionOptions sectionInsertMode:XLFormSectionInsertModeLastRow];
}
+(instancetype)formSectionWithTitle:(NSString *)title sectionOptions:(XLFormSectionOptions)sectionOptions sectionInsertMode:(XLFormSectionInsertMode)sectionInsertMode
{
return [[XLFormSectionDescriptor alloc] initWithTitle:title sectionOptions:sectionOptions sectionInsertMode:sectionInsertMode];
return [[[self class] alloc] initWithTitle:title sectionOptions:sectionOptions sectionInsertMode:sectionInsertMode];
}
-(BOOL)isMultivaluedSection
@@ -363,7 +363,18 @@
else{
self.hidePredicateCache = _hidden;
}
[self.hidePredicateCache boolValue] ? [self.formDescriptor hideFormSection:self] : [self.formDescriptor showFormSection:self] ;
if ([self.hidePredicateCache boolValue]){
if ([self.formDescriptor.delegate isKindOfClass:[XLFormViewController class]]){
XLFormBaseCell* firtResponder = (XLFormBaseCell*) [((XLFormViewController*)self.formDescriptor.delegate).tableView findFirstResponder];
if ([firtResponder isKindOfClass:[XLFormBaseCell class]] && firtResponder.rowDescriptor.sectionDescriptor == self){
[firtResponder resignFirstResponder];
}
}
[self.formDescriptor hideFormSection:self];
}
else{
[self.formDescriptor showFormSection:self];
}
return [self.hidePredicateCache boolValue];
}
+1 -1
View File
@@ -38,7 +38,7 @@
NSRange range;
for (int i = 1; i < tokens.count; i++) {
[new_string appendString:separator];
NSArray* subtokens = [[tokens[i] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" <>!=+-&|"]][0]
NSArray* subtokens = [[tokens[i] componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" <>!=+-&|()"]][0]
componentsSeparatedByString:@"."];
NSString* tag = subtokens[0];
NSString* attribute;
+1 -1
View File
@@ -29,5 +29,5 @@
@interface XLFormValidator : NSObject<XLFormValidatorProtocol>
+(XLFormValidator *)emailValidator;
+(XLFormValidator *)emailValidatorLong;
@end
+4 -1
View File
@@ -42,5 +42,8 @@
{
return [XLFormRegexValidator formRegexValidatorWithMsg:NSLocalizedString(@"Invalid email address", nil) regex:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,4}"];
}
+(XLFormValidator *)emailValidatorLong
{
return [XLFormRegexValidator formRegexValidatorWithMsg:NSLocalizedString(@"Invalid email address", nil) regex:@"[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,11}"];
}
@end
+1 -1
View File
@@ -26,7 +26,7 @@
#import "XLForm.h"
NSString * const XLFormRowDescriptorTypeText = @"text";
NSString *const XLFormRowDescriptorTypeText = @"text";
NSString *const XLFormRowDescriptorTypeName = @"name";
NSString *const XLFormRowDescriptorTypeURL = @"url";
NSString *const XLFormRowDescriptorTypeEmail = @"email";