Browse Source

first commit

YinBin 1 year ago
commit
aa4411d6e5
100 changed files with 8746 additions and 0 deletions
  1. 25 0
      .gitignore
  2. 8 0
      .travis.yml
  3. 137 0
      CHANGELOG.md
  4. 30 0
      Examples/Objective-C/Examples/AccessoryViews/AccessoryViewFormViewController.h
  5. 249 0
      Examples/Objective-C/Examples/AccessoryViews/AccessoryViewFormViewController.m
  6. 33 0
      Examples/Objective-C/Examples/AppDelegate.h
  7. 47 0
      Examples/Objective-C/Examples/AppDelegate.m
  8. 29 0
      Examples/Objective-C/Examples/CustomRows/CustomRowsViewController.h
  9. 150 0
      Examples/Objective-C/Examples/CustomRows/CustomRowsViewController.m
  10. 31 0
      Examples/Objective-C/Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.h
  11. 185 0
      Examples/Objective-C/Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.m
  12. 29 0
      Examples/Objective-C/Examples/CustomRows/Rating/RatingView/XLRatingView.h
  13. 66 0
      Examples/Objective-C/Examples/CustomRows/Rating/RatingView/XLRatingView.m
  14. 35 0
      Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.h
  15. 62 0
      Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.m
  16. 52 0
      Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.xib
  17. 13 0
      Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.h
  18. 17 0
      Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.m
  19. 41 0
      Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.xib
  20. 57 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/LxGridViewFlowLayout.h
  21. 408 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/LxGridViewFlowLayout.m
  22. 17 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZPhotoCell.h
  23. 624 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZPhotoCell.m
  24. 23 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZTestCell.h
  25. 100 0
      Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZTestCell.m
  26. 39 0
      Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.h
  27. 154 0
      Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.m
  28. 202 0
      Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.xib
  29. 35 0
      Examples/Objective-C/Examples/Dates/DateAndTimeValueTrasformer.h
  30. 89 0
      Examples/Objective-C/Examples/Dates/DateAndTimeValueTrasformer.m
  31. 31 0
      Examples/Objective-C/Examples/Dates/DatesFormViewController.h
  32. 191 0
      Examples/Objective-C/Examples/Dates/DatesFormViewController.m
  33. BIN
      Examples/Objective-C/Examples/Dates/XLForm-Dates.gif
  34. 30 0
      Examples/Objective-C/Examples/ExamplesFormViewController.h
  35. 200 0
      Examples/Objective-C/Examples/ExamplesFormViewController.m
  36. 13 0
      Examples/Objective-C/Examples/Formatters/FormattersViewController.h
  37. 120 0
      Examples/Objective-C/Examples/Formatters/FormattersViewController.m
  38. 30 0
      Examples/Objective-C/Examples/Inputs/InputsFormViewController.h
  39. 167 0
      Examples/Objective-C/Examples/Inputs/InputsFormViewController.m
  40. BIN
      Examples/Objective-C/Examples/Inputs/XLForm-Inputs.gif
  41. 45 0
      Examples/Objective-C/Examples/MultiValuedSections/MultivaluedFormViewController.h
  42. 336 0
      Examples/Objective-C/Examples/MultiValuedSections/MultivaluedFormViewController.m
  43. BIN
      Examples/Objective-C/Examples/MultiValuedSections/XLForm-MultiValuedSections.gif
  44. 30 0
      Examples/Objective-C/Examples/Others/CustomCells/XLFormCustomCell.h
  45. 60 0
      Examples/Objective-C/Examples/Others/CustomCells/XLFormCustomCell.m
  46. 36 0
      Examples/Objective-C/Examples/Others/CustomCells/XLFormImageSelectorCell.h
  47. 296 0
      Examples/Objective-C/Examples/Others/CustomCells/XLFormImageSelectorCell.m
  48. 31 0
      Examples/Objective-C/Examples/Others/OthersFormViewController.h
  49. 249 0
      Examples/Objective-C/Examples/Others/OthersFormViewController.m
  50. BIN
      Examples/Objective-C/Examples/Others/XLForm-Boolean.gif
  51. BIN
      Examples/Objective-C/Examples/Others/XLForm-stepCounter.gif
  52. 31 0
      Examples/Objective-C/Examples/PredicateExamples/BasicPredicateViewController.h
  53. 84 0
      Examples/Objective-C/Examples/PredicateExamples/BasicPredicateViewController.m
  54. 31 0
      Examples/Objective-C/Examples/PredicateExamples/BlogExampleViewController.h
  55. 106 0
      Examples/Objective-C/Examples/PredicateExamples/BlogExampleViewController.m
  56. 31 0
      Examples/Objective-C/Examples/PredicateExamples/PredicateFormViewController.h
  57. 116 0
      Examples/Objective-C/Examples/PredicateExamples/PredicateFormViewController.m
  58. BIN
      Examples/Objective-C/Examples/PredicateExamples/XLFormPredicates.gif
  59. BIN
      Examples/Objective-C/Examples/PredicateExamples/XLFormPredicatesBasic.gif
  60. 34 0
      Examples/Objective-C/Examples/RealExamples/NativeEventFormViewController.h
  61. 263 0
      Examples/Objective-C/Examples/RealExamples/NativeEventFormViewController.m
  62. BIN
      Examples/Objective-C/Examples/RealExamples/XLForm.gif
  63. 30 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.h
  64. 73 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.m
  65. 30 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.h
  66. 48 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.m
  67. 32 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.h
  68. 108 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.m
  69. 20 0
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.xib
  70. BIN
      Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/XLForm-map-custom-selector.gif
  71. 31 0
      Examples/Objective-C/Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.h
  72. 94 0
      Examples/Objective-C/Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.m
  73. 34 0
      Examples/Objective-C/Examples/Selectors/DynamicSelector/UsersTableViewController.h
  74. 255 0
      Examples/Objective-C/Examples/Selectors/DynamicSelector/UsersTableViewController.m
  75. BIN
      Examples/Objective-C/Examples/Selectors/DynamicSelector/XLForm-dynamic-custom-selector.gif
  76. 32 0
      Examples/Objective-C/Examples/Selectors/HTTPSessionManager.h
  77. 45 0
      Examples/Objective-C/Examples/Selectors/HTTPSessionManager.m
  78. 11 0
      Examples/Objective-C/Examples/Selectors/Helpers/Data/Model.xcdatamodeld/Model.xcdatamodel/contents
  79. 31 0
      Examples/Objective-C/Examples/Selectors/SelectorsFormViewController.h
  80. 389 0
      Examples/Objective-C/Examples/Selectors/SelectorsFormViewController.m
  81. BIN
      Examples/Objective-C/Examples/Selectors/XLForm-Selectors.gif
  82. 335 0
      Examples/Objective-C/Examples/StoryboardExample/iPhoneStoryboard.storyboard
  83. 30 0
      Examples/Objective-C/Examples/UICustomization/UICustomizationFormViewController.h
  84. 90 0
      Examples/Objective-C/Examples/UICustomization/UICustomizationFormViewController.m
  85. 30 0
      Examples/Objective-C/Examples/Validations/ValidationExamplesFormViewController.h
  86. 160 0
      Examples/Objective-C/Examples/Validations/ValidationExamplesFormViewController.m
  87. 22 0
      Examples/Objective-C/Inline Segmented/XLFormInlineSegmentedCell.h
  88. 194 0
      Examples/Objective-C/Inline Segmented/XLFormInlineSegmentedCell.m
  89. 17 0
      Examples/Objective-C/Podfile
  90. 836 0
      Examples/Objective-C/XLForm.xcodeproj/project.pbxproj
  91. 7 0
      Examples/Objective-C/XLForm.xcodeproj/project.xcworkspace/contents.xcworkspacedata
  92. 1 0
      Examples/Objective-C/XLForm.xcworkspace/contents.xcworkspacedata
  93. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AlbumAddBtn.imageset/AlbumAddBtn@2x.png
  94. 21 0
      Examples/Objective-C/XLForm/Images.xcassets/AlbumAddBtn.imageset/Contents.json
  95. 192 0
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/Contents.json
  96. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_114.png
  97. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_120.png
  98. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_152.png
  99. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_57.png
  100. BIN
      Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_76.png

+ 25 - 0
.gitignore

@@ -0,0 +1,25 @@
+# Xcode
+.DS_Store
+*/build/*
+*.pbxuser
+!default.pbxuser
+*.mode1v3
+!default.mode1v3
+*.mode2v3
+!default.mode2v3
+*.perspectivev3
+!default.perspectivev3
+xcuserdata
+profile
+*.moved-aside
+DerivedData
+.idea/
+*.hmap
+*.xccheckout
+
+#CocoaPods
+Pods
+Tests/Pods
+Tests/Podfile.lock
+Examples/Objective-C/Podfile.lock
+Examples/Swift/Podfile.lock

+ 8 - 0
.travis.yml

@@ -0,0 +1,8 @@
+language: objective-c
+osx_image: xcode8.2
+before_install:
+    - gem install cocoapods --no-rdoc --no-ri --no-document --quiet
+    - gem install xcpretty --no-rdoc --no-ri --no-document --quiet
+    - cd Tests && pod install && cd $TRAVIS_BUILD_DIR
+script: rake test
+

+ 137 - 0
CHANGELOG.md

@@ -0,0 +1,137 @@
+# Change Log
+All notable changes to this project will be documented in this file.
+
+### Version 3.3.0:
+* Added `cellConfigForSelector` to style XLFormOptionsViewController
+* Added properties to **limit number of characters** in `XLFormTextFieldCell` and `XLFormTextViewCell`
+* Minor fixes
+
+### Version 3.2.0:
+* Added XL_APP_EXTENSIONS macro to allow app extensions (@MuscleRumble #357)
+* Added shouldChangeTextInRange delegate call for UITextView. (@kiancheong #782)
+* Added support for NSFormatter (@ziogaschr, @fwhenin, @bhirt-bpl #306)
+* Added `height` property to XLFormRowDescriptor to allow setting height of individual cells.
+
+### Version 3.1.2:
+* Update row in `cellForRowAtIndexPath` instead of `willDisplayCell`
+* Added cancel action to image selector (by koenpunt)
+* Other minor fixes
+
+### Version 3.1.1
+* Allow setting width percentage on UITextView
+* Added custom inline row example
+* Fixed bug where XLFormImageCell was not added to project
+* Add ability to `end editing` on scroll
+* Other bugs and refactor
+
+### Version 3.1.0
+* Added Carthage support
+* Added NSCoding protocol
+* Allowed HTTP connections
+* Several bugfixes and improvements.
+
+### 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.
+* Added `XLFormRowDescriptorTypeCountDownTimerInline` and `XLFormRowDescriptorTypeCountDownTimer` row type with an example.
+* Deleted `dateFormatter` property and added support to use the `NSValueTransformer` to convert the selected object to a NSString in the XLFormDateCell class.
+
+* Added `XLFormRowDescriptorTypeCountDownTimerInline` and `XLFormRowDescriptorTypeCountDownTimer` row type with an example.
+* Deleted `dateFormatter` property and added support to use the `NSValueTransformer` to convert the selected object to a NSString in the XLFormDateCell class.
+
+
+### Version 2.2.0
+
+* Fixed "(null)" caption when `XLFormRowDescriptorTypeSelectorLeftRight` row required error message is shown.
+* Refresh the cell content instead of recreating one, when the form get back from a selection.
+* Added XLFormRowDescriptor to validations error to easily show an error mask.
+* Use row tag in validation error message if row does not have a title. It is also possible to set up a custom message if needed
+* Added a convenience method to add a XLFormRowDescriptor instance before another one.
+* Allow nil values in cellConfig and cellConfigAtConfigure.
+* Fix constraints for textFieldCell when it is configured to be right aligned.
+* Add asterisk to required segmentedCells if needed.
+* Fail validation for empty strings and NSNull on required rows.
+* Segue support added to buttons and selectors.
+* Ability to configure a storyboardId or a viewController nibName to by used by button and selector rows as presented view controller.
+* Fix scrolling to top when status bar is tapped.
+* Fix wrong type of XLFormRowDescriptorTypeDecimal row. Now it's converted to NSNumber.
+* Fix issue: XLFormRegexValidator only checks regex validation for NSStrings, not working for number.
+* Callconfigure method from awakeFromNib on XLFormBaseCell.
+* Assign form.delegate from inside setForm: method.
+* Added custom cell, validation, reordering, can insert, can delete examples.
+* Added support for inputAccessoryView. Default input accessory view allows to navigate among rows. Fully optionally and customizable.
+* Added suport for row navigation. Fully optionally and customizable.
+* beginEditing: endEditing: methods added. These method are called each time a row gains / loses firstResponder. They bring the ability to do UI changes.
+* Read Only mode added. `disable` property added to XLFormDescriptor class.
+* Rename `label` XLFormTextViewCell property as `textLabel`.
+* fix position of multivalued section accessory view.
+* Can delete, can delete, can reorder section mode added. it's possible to enable some of them, don't need to enable all modes.
+
+### Version 2.1.0
+
+* Change `XLFormRowDescriptorTypeText`, `XLFormRowDescriptorTypeName` and `XLFormRowDescriptorTypeTextView` keyboard type to `UIKeyboardTypeDefault`.
+* Added `XLFormRowDescriptorTypeInfo` row type and example.
+* Added `XLFormRowDescriptorTypeSelectorPopover` row type and example.
+* CI added. Created Test project into Tests folder and set up Travis.
+* Documented how to customize UI. Added an example.
+* Now XLFormViewController extends from UIViewController instead of UITableViewController.
+* Added tableView property as a XLFormViewController IBOutlet.
+* Added support for storyboard reuse identifier and nib file.
+* Button selection can be handled using a selector or block.
+* Added addAsteriskToRequiredRowsTitle property to XLFormDescriptor. NO is used as value by default.
+* Image cell has been removed because it depends on AFNetworking and now needs to be implemented as a custom cell. You can find the image custom cell in Examples/Others/CustomCells.
+
+### Version 2.0.0
+
+* Added `XLFormRowDescriptorTypeMultipleSelector` row type and example.
+* Added `XLFormRowDescriptorTypeSelectorPickerView` row type and example.
+* Added `XLFormRowDescriptorTypeSelectorPickerViewInline` row type and example.
+* Added generic way to create inline selector rows.
+* Ability to customize row animations.
+* `(NSDictionary *)formValues;` XLFormViewController method added in order to get raw form data.
+* Added `XLFormRowDescriptorTypeSelectorSegmentedControl` row type and example.
+* AFNetworking dependency removed.
+* Added `XLFormRowDescriptorTypeStepCounter` row type and related example.
+
+
+### Version 1.0.1
+
+* Added storyboard example.
+* Added button `XLFormRowDescriptorTypeButton` example.
+* Documented how to add a custom row.
+* Fixed issues: [#2](https://github.com/xmartlabs/XLForm/issues/2 "#2"), [#3](https://github.com/xmartlabs/XLForm/issues/3 "#3"), [#27](https://github.com/xmartlabs/XLForm/issues/27 "#27"), [#38](https://github.com/xmartlabs/XLForm/issues/38 "#38").
+* Fixed crash caused by inline date rows. [#6](https://github.com/xmartlabs/XLForm/issues/6 "#6")
+* Fixed ipad issue *invalid cell layout*. [#10](https://github.com/xmartlabs/XLForm/issues/10 "#10")
+* New convenience methods to insert sections dinamically. [#13](https://github.com/xmartlabs/XLForm/pull/13 "#13")
+* Change default label style to `UIFontTextStyleBody`. [#18](https://github.com/xmartlabs/XLForm/issues/18 "#18")
+* Added step counter row, `XLFormRowDescriptorTypeStepCounter`.
+* Added `initWithCoder` initializer to `XLFormViewController`. [#32](https://github.com/xmartlabs/XLForm/issues/32 "#32").
+* Added a convenience method to deselect a `XLFormRowDescriptor`. `-(void)deselectFormRow:(XLFormRowDescriptor *)row;`. [#33](https://github.com/xmartlabs/XLForm/issues/33 "#33").
+
+
+### Version 1.0.0 
+
+* Initial release

+ 30 - 0
Examples/Objective-C/Examples/AccessoryViews/AccessoryViewFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  AccessoryViewFormViewController.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 "XLFormViewController.h"
+
+@interface AccessoryViewFormViewController : XLFormViewController
+
+@end

+ 249 - 0
Examples/Objective-C/Examples/AccessoryViews/AccessoryViewFormViewController.m

@@ -0,0 +1,249 @@
+//
+//  AccessoryViewFormViewController.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 "XLForm.h"
+#import "AccessoryViewFormViewController.h"
+
+//This macro defines if we use predicates to hide rows or do it manually the old way.
+//Just comment out if you want it to run without predicates.
+#define USE_PREDICATES_FOR_HIDING
+
+@interface AccessoryViewFormViewController ()
+
+@end
+
+@implementation AccessoryViewFormViewController
+{
+#ifndef USE_PREDICATES_FOR_HIDING
+    XLFormRowDescriptor * _rowShowAccessoryView;
+    XLFormRowDescriptor * _rowStopDisableRow;
+    XLFormRowDescriptor * _rowStopInlineRow;
+    XLFormRowDescriptor * _rowSkipCanNotBecomeFirstResponderRow;
+#endif
+}
+
+
+NSString * kAccessoryViewRowNavigationEnabled               = @"kRowNavigationEnabled";
+NSString * kAccessoryViewRowNavigationShowAccessoryView     = @"kRowNavigationShowAccessoryView";
+NSString * kAccessoryViewRowNavigationStopDisableRow        = @"rowNavigationStopDisableRow";
+NSString * kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow = @"rowNavigationSkipCanNotBecomeFirstResponderRow";
+NSString * kAccessoryViewRowNavigationStopInlineRow = @"rowNavigationStopInlineRow";
+NSString * kAccessoryViewName = @"name";
+NSString * kAccessoryViewEmail = @"email";
+NSString * kAccessoryViewTwitter = @"twitter";
+NSString * kAccessoryViewUrl = @"url";
+NSString * kAccessoryViewDate = @"date";
+NSString * kAccessoryViewTextView = @"textView";
+NSString * kAccessoryViewCheck = @"check";
+NSString * kAccessoryViewNotes = @"notes";
+
+
+
+
+-(id)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+-(void)initializeForm
+{
+    XLFormDescriptor * formDescriptor = [XLFormDescriptor formDescriptorWithTitle:@"Accessory View"];
+    formDescriptor.rowNavigationOptions = XLFormRowNavigationOptionEnabled;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    XLFormRowDescriptor * switchRow;
+    
+    // Configuration section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Row Navigation Settings"];
+    section.footerTitle = @"Changing the Settings values you will navigate differently";
+    [formDescriptor addFormSection:section];
+    
+    // RowNavigationEnabled
+    switchRow = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationEnabled rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Row Navigation Enabled?"];
+    switchRow.value = @YES;
+    [section addFormRow:switchRow];
+    
+    // RowNavigationShowAccessoryView
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationShowAccessoryView rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Show input accessory row?"];
+    row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionEnabled) == XLFormRowNavigationOptionEnabled);
+    [section addFormRow:row];
+#ifdef USE_PREDICATES_FOR_HIDING
+    row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
+#else
+    _rowShowAccessoryView = row;
+#endif
+    
+    // RowNavigationStopDisableRow
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopDisableRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach disabled row?"];
+    row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopDisableRow) == XLFormRowNavigationOptionStopDisableRow);
+    [section addFormRow:row];
+#ifdef USE_PREDICATES_FOR_HIDING
+    row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
+#else
+    _rowStopDisableRow = row;
+#endif
+    
+    // RowNavigationStopInlineRow
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationStopInlineRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Stop when reach inline row?"];
+    row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionStopInlineRow) == XLFormRowNavigationOptionStopInlineRow);
+    [section addFormRow:row];
+#ifdef USE_PREDICATES_FOR_HIDING
+    row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
+#else
+    _rowStopInlineRow = row;
+#endif
+    
+    // RowNavigationSkipCanNotBecomeFirstResponderRow
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Skip Can Not Become First Responder Row?"];
+    row.value = @((formDescriptor.rowNavigationOptions & XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow) == XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow);
+    [section addFormRow:row];
+#ifdef USE_PREDICATES_FOR_HIDING
+    row.hidden = [NSString stringWithFormat:@"$%@ == 0", switchRow];
+#else
+    _rowSkipCanNotBecomeFirstResponderRow = row;
+#endif
+    
+
+    
+    // Basic Information - Section
+    section = [XLFormSectionDescriptor formSection];
+    [formDescriptor addFormSection:section];
+    
+    // Name
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewName rowType:XLFormRowDescriptorTypeText title:@"Name"];
+    row.required = YES;
+    [section addFormRow:row];
+    
+    // Email
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewEmail rowType:XLFormRowDescriptorTypeEmail title:@"Email"];
+    // validate the email
+    [row addValidator:[XLFormValidator emailValidator]];
+    [section addFormRow:row];
+    
+    // Twitter
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewTwitter rowType:XLFormRowDescriptorTypeTwitter title:@"Twitter"];
+    row.disabled = @YES;
+    row.value = @"@no_editable";
+    [section addFormRow:row];
+    
+    // Url
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewUrl rowType:XLFormRowDescriptorTypeURL title:@"Url"];
+    [section addFormRow:row];
+    
+    // Url
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewDate rowType:XLFormRowDescriptorTypeDateInline title:@"Date Inline"];
+    row.value = [NSDate new];
+    [section addFormRow:row];
+    
+    
+    section = [XLFormSectionDescriptor formSection];
+    [formDescriptor addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewTextView rowType:XLFormRowDescriptorTypeTextView];
+    [row.cellConfigAtConfigure setObject:@"TEXT VIEW EXAMPLE" forKey:@"textView.placeholder"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Check"];
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSection];
+    [formDescriptor addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kAccessoryViewNotes rowType:XLFormRowDescriptorTypeTextView title:@"Notes"];
+    [section addFormRow:row];
+    
+    self.form = formDescriptor;
+}
+
+
+
+#pragma mark - XLFormDescriptorDelegate
+
+-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)rowDescriptor oldValue:(id)oldValue newValue:(id)newValue
+{
+    [super formRowDescriptorValueHasChanged:rowDescriptor oldValue:oldValue newValue:newValue];
+#ifndef USE_PREDICATES_FOR_HIDING
+    NSString * kRowNavigationEnabled        = @"kRowNavigationEnabled";
+    if ([rowDescriptor.tag isEqualToString:kRowNavigationEnabled]){
+        if ([[rowDescriptor.value valueData] isEqual:@NO]){
+            self.form.rowNavigationOptions = XLFormRowNavigationOptionNone;
+            [self.form removeFormRowWithTag:kAccessoryViewRowNavigationShowAccessoryView];
+            [self.form removeFormRowWithTag:kAccessoryViewRowNavigationStopDisableRow];
+            [self.form removeFormRowWithTag:kAccessoryViewRowNavigationStopInlineRow];
+            [self.form removeFormRowWithTag:kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow];
+        }
+        else{
+            self.form.rowNavigationOptions = XLFormRowNavigationOptionEnabled;
+            _rowShowAccessoryView.value = @YES;
+            _rowStopDisableRow.value = @NO;
+            _rowStopInlineRow.value = @NO;
+            _rowSkipCanNotBecomeFirstResponderRow.value = @NO;
+            [self.form addFormRow:_rowShowAccessoryView afterRow:rowDescriptor];
+            [self.form addFormRow:_rowStopDisableRow afterRow:_rowShowAccessoryView];
+            [self.form addFormRow:_rowStopInlineRow afterRow:_rowStopDisableRow];
+            [self.form addFormRow:_rowSkipCanNotBecomeFirstResponderRow afterRow:_rowStopInlineRow];
+            
+        }
+    }
+    else
+#endif
+    if ([rowDescriptor.tag isEqualToString:kAccessoryViewRowNavigationStopDisableRow]){
+        if ([[rowDescriptor.value valueData] isEqual:@(YES)]){
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptionStopDisableRow;
+        }
+        else{
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions & (~XLFormRowNavigationOptionStopDisableRow);
+        }
+    }
+    else if ([rowDescriptor.tag isEqualToString:kAccessoryViewRowNavigationStopInlineRow]){
+        if ([[rowDescriptor.value valueData] isEqual:@(YES)]){
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptionStopInlineRow;
+        }
+        else{
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions & (~XLFormRowNavigationOptionStopInlineRow);
+        }
+    }
+    else if ([rowDescriptor.tag isEqualToString:kAccessoryViewRowNavigationSkipCanNotBecomeFirstResponderRow]){
+        if ([[rowDescriptor.value valueData] isEqual:@(YES)]){
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions | XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow;
+        }
+        else{
+            self.form.rowNavigationOptions = self.form.rowNavigationOptions & (~XLFormRowNavigationOptionSkipCanNotBecomeFirstResponderRow);
+        }
+    }
+}
+
+-(UIView *)inputAccessoryViewForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor
+{
+    if ([[[self.form formRowWithTag:kAccessoryViewRowNavigationShowAccessoryView].value valueData] isEqual:@NO]){
+        return nil;
+    }
+    return [super inputAccessoryViewForRowDescriptor:rowDescriptor];
+}
+
+@end

+ 33 - 0
Examples/Objective-C/Examples/AppDelegate.h

@@ -0,0 +1,33 @@
+//
+//  AppDelegate.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 <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+
+@property (strong, nonatomic) UIWindow *window;
+
+
+@end

+ 47 - 0
Examples/Objective-C/Examples/AppDelegate.m

@@ -0,0 +1,47 @@
+//
+//  AppDelegate.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 "ExamplesFormViewController.h"
+#import "AppDelegate.h"
+
+
+@implementation AppDelegate
+
+
+- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
+{
+    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+    // Override point for customization after application launch.
+    self.window.backgroundColor = [UIColor whiteColor];
+    
+    // load the initial form form Storybiard
+    UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"iPhoneStoryboard" bundle:nil];
+    [self.window setRootViewController:[storyboard instantiateInitialViewController]];
+    [self.window makeKeyAndVisible];
+    return YES;
+}
+
+
+@end

+ 29 - 0
Examples/Objective-C/Examples/CustomRows/CustomRowsViewController.h

@@ -0,0 +1,29 @@
+//  CustomRowsViewController.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 "XLFormViewController.h"
+
+@interface CustomRowsViewController : XLFormViewController
+
+@end

+ 150 - 0
Examples/Objective-C/Examples/CustomRows/CustomRowsViewController.m

@@ -0,0 +1,150 @@
+//  CustomRowsViewController.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 "CustomRowsViewController.h"
+#import "XLForm.h"
+#import "XLFormWeekDaysCell.h"
+#import "XLFormRatingCell.h"
+#import "FloatLabeledTextFieldCell.h"
+#import "XLFormCustomCell.h"
+#import "XLFormInlineSegmentedCell.h"
+#import "TZPhotoCell.h"
+#import "FYSectionCell.h"
+
+static NSString * const kCustomRowFirstRatingTag           = @"CustomRowFirstRatingTag";
+static NSString * const kCustomRowSecondRatingTag          = @"CustomRowSecondRatingTag";
+static NSString * const kCustomRowFloatLabeledTextFieldTag = @"CustomRowFloatLabeledTextFieldTag";
+static NSString * const kCustomRowWeekdays                 = @"CustomRowWeekdays";
+static NSString * const kCustomInline                      = @"kCustomInline";
+static NSString * const kCustomPhoto                       = @"kCustomPhoto";
+static NSString * const kCustomRowText                     = @"kCustomText";
+
+@implementation CustomRowsViewController
+
+-(id)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+-(void)initializeForm
+{
+    XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"Custom Rows"];
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    // Section Ratings
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Ratings"];
+    [form addFormSection:section];
+    
+    row       = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowFirstRatingTag rowType:XLFormRowDescriptorTypeRate title:@"First Rating"];
+    row.value = @(3);
+    [section addFormRow:row];
+    
+    row       = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowSecondRatingTag rowType:XLFormRowDescriptorTypeRate title:@"Second Rating"];
+    row.value = @(1);
+    [section addFormRow:row];
+    
+    // Section Float Labeled Text Field
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Float Labeled Text Field"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowFloatLabeledTextFieldTag rowType:XLFormRowDescriptorTypeFloatLabeledTextField title:@"Title"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowFloatLabeledTextFieldTag rowType:XLFormRowDescriptorTypeFloatLabeledTextField title:@"First Name"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowFloatLabeledTextFieldTag rowType:XLFormRowDescriptorTypeFloatLabeledTextField title:@"Last Name"];
+    [section addFormRow:row];
+    
+    // Section Weekdays
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Weekdays"];
+    [form addFormSection:section];
+    
+    // WeekDays
+    row       = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowWeekdays rowType:XLFormRowDescriptorTypeWeekDays];
+    row.value = @{
+                  kSunday: @(NO),
+                  kMonday: @(YES),
+                  kTuesday: @(YES),
+                  kWednesday: @(NO),
+                  kThursday: @(NO),
+                  kFriday: @(NO),
+                  kSaturday: @(NO)
+                  };
+    [section addFormRow:row];
+    
+    // Custom Inline Segmented row
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Custom Inline"];
+    [form addFormSection:section];
+    
+    // Inline segmented
+    row                 = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomInline rowType:XLFormRowDescriptorTypeSegmentedInline];
+    row.title           = @"You support...";
+    row.selectorOptions = @[@"Uruguay", @"Brazil", @"Argentina", @"Chile"];
+    row.value           = @"Uruguay";
+    [section addFormRow:row];
+    
+    
+    // Custom Photo row
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Custom Photo"];
+    [form addFormSection:section];
+    
+    XLFormRowDescriptor *rowDesc = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomPhoto rowType:XLFormRowDescriptorTypePhotoView];
+    rowDesc.cellClass            = [TZPhotoCell class];
+    //    TODO 待实现功能:回显网络图片、取图批量上传
+    [section addFormRow:rowDesc];
+    
+    
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    
+    XLFormRowDescriptor *customRowDescriptor = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomRowText rowType:@"XLFormRowDescriptorTypeCustom"];
+    // Must set custom cell or add custom cell to cellClassesForRowDescriptorTypes dictionary before XLFormViewController loaded
+    customRowDescriptor.cellClass = [XLFormCustomCell class];
+    [section addFormRow:customRowDescriptor];
+    
+    self.form = form;
+}
+
+-(UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{
+    if (section == 1) {
+        FYSectionCell *sectionCell = [[NSBundle mainBundle]loadNibNamed:@"FYSectionCell" owner:nil options:nil].lastObject;
+        return sectionCell;
+    }
+    return nil;
+}
+
+-(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{
+    if(section == 1){
+        return 50;
+    }
+    return 0;
+}
+
+@end

+ 31 - 0
Examples/Objective-C/Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.h

@@ -0,0 +1,31 @@
+//  FloatLabeledTextFieldCell.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 "XLFormBaseCell.h"
+
+extern NSString * const XLFormRowDescriptorTypeFloatLabeledTextField;
+
+@interface FloatLabeledTextFieldCell : XLFormBaseCell
+
+@end

+ 185 - 0
Examples/Objective-C/Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.m

@@ -0,0 +1,185 @@
+//  FloatLabeledTextFieldCell.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 "FloatLabeledTextFieldCell.h"
+#import "UIView+XLFormAdditions.h"
+#import "JVFloatLabeledTextField.h"
+#import "NSObject+XLFormAdditions.h"
+
+#import <JVFloatLabeledTextField/JVFloatLabeledTextField.h>
+
+NSString * const XLFormRowDescriptorTypeFloatLabeledTextField = @"XLFormRowDescriptorTypeFloatLabeledTextField";
+
+const static CGFloat kVMargin = 8.0f;
+const static CGFloat kFloatingLabelFontSize = 11.0f;
+
+@interface FloatLabeledTextFieldCell () <UITextFieldDelegate>
+@property (nonatomic) JVFloatLabeledTextField * floatLabeledTextField;
+@end
+
+@implementation FloatLabeledTextFieldCell
+
+@synthesize floatLabeledTextField =_floatLabeledTextField;
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:[FloatLabeledTextFieldCell class] forKey:XLFormRowDescriptorTypeFloatLabeledTextField];
+}
+
+-(JVFloatLabeledTextField *)floatLabeledTextField
+{
+    if (_floatLabeledTextField) return _floatLabeledTextField;
+    
+    _floatLabeledTextField = [JVFloatLabeledTextField autolayoutView];
+    _floatLabeledTextField.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody];
+    _floatLabeledTextField.floatingLabel.font = [UIFont boldSystemFontOfSize:kFloatingLabelFontSize];
+
+    _floatLabeledTextField.clearButtonMode = UITextFieldViewModeWhileEditing;
+    return _floatLabeledTextField;
+}
+
+#pragma mark - XLFormDescriptorCell
+
+-(void)configure
+{
+    [super configure];
+    [self setSelectionStyle:UITableViewCellSelectionStyleNone];
+    [self.contentView addSubview:self.floatLabeledTextField];
+    [self.floatLabeledTextField setDelegate:self];
+    [self.contentView addConstraints:[self layoutConstraints]];
+}
+
+-(void)update
+{
+    [super update];
+    
+    self.floatLabeledTextField.attributedPlaceholder =
+    [[NSAttributedString alloc] initWithString:self.rowDescriptor.title
+                                    attributes:@{NSForegroundColorAttributeName: [UIColor lightGrayColor]}];
+    
+    self.floatLabeledTextField.text = self.rowDescriptor.value ? [self.rowDescriptor.value displayText] : self.rowDescriptor.noValueDisplayText;
+    [self.floatLabeledTextField setEnabled:!self.rowDescriptor.isDisabled];
+    
+    self.floatLabeledTextField.floatingLabelTextColor = [UIColor lightGrayColor];
+    
+    [self.floatLabeledTextField setAlpha:((self.rowDescriptor.isDisabled) ? .6 : 1)];
+}
+
+-(BOOL)formDescriptorCellCanBecomeFirstResponder
+{
+    return !self.rowDescriptor.isDisabled;
+}
+
+-(BOOL)formDescriptorCellBecomeFirstResponder
+{
+    return [self.floatLabeledTextField becomeFirstResponder];
+}
+
+#pragma mark - UITextFieldDelegate
+
+- (BOOL)textFieldShouldClear:(UITextField *)textField
+{
+    return [self.formViewController textFieldShouldClear:textField];
+}
+
+- (BOOL)textFieldShouldReturn:(UITextField *)textField
+{
+    return [self.formViewController textFieldShouldReturn:textField];
+}
+
+- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField
+{
+    return [self.formViewController textFieldShouldBeginEditing:textField];
+}
+
+- (BOOL)textFieldShouldEndEditing:(UITextField *)textField
+{
+    return [self.formViewController textFieldShouldEndEditing:textField];
+}
+
+- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {
+    return [self.formViewController textField:textField shouldChangeCharactersInRange:range replacementString:string];
+}
+
+- (void)textFieldDidBeginEditing:(UITextField *)textField
+{
+    [self.formViewController textFieldDidBeginEditing:textField];
+}
+
+- (void)textFieldDidEndEditing:(UITextField *)textField
+{
+    [self textFieldDidChange:textField];
+    [self.formViewController textFieldDidEndEditing:textField];
+}
+
+-(void)setReturnKeyType:(UIReturnKeyType)returnKeyType
+{
+    self.floatLabeledTextField.returnKeyType = returnKeyType;
+}
+
+-(UIReturnKeyType)returnKeyType
+{
+    return self.floatLabeledTextField.returnKeyType;
+}
+
++(CGFloat)formDescriptorCellHeightForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor {
+    return 55;
+}
+
+
+
+-(NSArray *)layoutConstraints
+{
+    NSMutableArray * result = [[NSMutableArray alloc] init];
+
+    NSDictionary * views = @{@"floatLabeledTextField": self.floatLabeledTextField};
+    NSDictionary *metrics = @{@"vMargin":@(kVMargin)};
+    
+    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[floatLabeledTextField]-|"
+                                                                                               options:0
+                                                                                               metrics:metrics
+                                                                                                 views:views]];
+    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(vMargin)-[floatLabeledTextField]-(vMargin)-|"
+                                                                                               options:0
+                                                                                               metrics:metrics
+                                                                                                 views:views]];
+    return result;
+}
+
+#pragma mark - Helpers
+
+- (void)textFieldDidChange:(UITextField *)textField
+{
+    if (self.floatLabeledTextField == textField) {
+        if ([self.floatLabeledTextField.text length] > 0) {
+            self.rowDescriptor.value = self.floatLabeledTextField.text;
+        } else {
+            self.rowDescriptor.value = nil;
+        }
+    }
+}
+
+
+
+@end

+ 29 - 0
Examples/Objective-C/Examples/CustomRows/Rating/RatingView/XLRatingView.h

@@ -0,0 +1,29 @@
+//  XLRatingView.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 <AXRatingView/AXRatingView.h>
+
+@interface XLRatingView : AXRatingView
+
+@end

+ 66 - 0
Examples/Objective-C/Examples/CustomRows/Rating/RatingView/XLRatingView.m

@@ -0,0 +1,66 @@
+//  XLRatingView.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 "XLRatingView.h"
+
+@implementation XLRatingView
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self customize];
+    }
+    return self;
+}
+
+- (instancetype)initWithFrame:(CGRect)frame
+{
+    self = [super initWithFrame:frame];
+    if (self) {
+        [self customize];
+    }
+    return self;
+}
+
+- (id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+    if (self) {
+        [self customize];
+    }
+    return self;
+}
+
+- (void)customize
+{
+    self.baseColor = [UIColor colorWithRed:(205/255.0) green:(201/255.0) blue:(201/255.0) alpha:1];
+    self.highlightColor = [UIColor colorWithRed:(255/255.0) green:(215/255.0) blue:0 alpha:1];
+    self.markFont = [UIFont systemFontOfSize:23.0f];
+    self.translatesAutoresizingMaskIntoConstraints = NO;
+    self.stepInterval = 1.0f;
+}
+
+@end
+

+ 35 - 0
Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.h

@@ -0,0 +1,35 @@
+//  XLFormRatingCell.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 "XLFormBaseCell.h"
+#import "XLRatingView.h"
+
+extern NSString * const XLFormRowDescriptorTypeRate;
+
+@interface XLFormRatingCell : XLFormBaseCell
+
+@property (weak, nonatomic) IBOutlet UILabel *rateTitle;
+@property (weak, nonatomic) IBOutlet XLRatingView *ratingView;
+
+@end

+ 62 - 0
Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.m

@@ -0,0 +1,62 @@
+//  XLFormRatingCell.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 "XLFormRatingCell.h"
+
+NSString * const XLFormRowDescriptorTypeRate = @"XLFormRowDescriptorTypeRate";
+
+@implementation XLFormRatingCell
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:NSStringFromClass([XLFormRatingCell class]) forKey:XLFormRowDescriptorTypeRate];
+}
+
+- (void)configure
+{
+    [super configure];
+    
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    [self.ratingView addTarget:self action:@selector(rateChanged:) forControlEvents:UIControlEventValueChanged];
+}
+
+- (void)update
+{
+    [super update];
+    
+    self.ratingView.value = [self.rowDescriptor.value floatValue];
+    self.rateTitle.text = self.rowDescriptor.title;
+    
+    [self.ratingView setAlpha:((self.rowDescriptor.isDisabled) ? .6 : 1)];
+    [self.rateTitle setAlpha:((self.rowDescriptor.isDisabled) ? .6 : 1)];
+}
+
+#pragma mark - Events
+
+-(void)rateChanged:(AXRatingView *)ratingView
+{
+    self.rowDescriptor.value = [NSNumber numberWithFloat:ratingView.value];
+}
+
+@end

+ 52 - 0
Examples/Objective-C/Examples/CustomRows/Rating/XLFormRatingCell.xib

@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
+        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" id="OGo-4x-YLf" customClass="XLFormRatingCell">
+            <rect key="frame" x="0.0" y="0.0" width="478" height="44"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="OGo-4x-YLf" id="hV6-xt-6pq">
+                <rect key="frame" x="0.0" y="0.0" width="478" height="43"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="yhI-dj-sRk" customClass="XLRatingView">
+                        <rect key="frame" x="355" y="11" width="115" height="22"/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="22" id="85e-Ov-qM7"/>
+                            <constraint firstAttribute="width" constant="115" id="kOb-W4-HPs"/>
+                        </constraints>
+                    </view>
+                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Rate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Vxp-gw-YTt">
+                        <rect key="frame" x="8" y="11" width="347" height="21"/>
+                        <constraints>
+                            <constraint firstAttribute="height" constant="21" id="IK4-8e-SFs"/>
+                        </constraints>
+                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
+                        <nil key="highlightedColor"/>
+                    </label>
+                </subviews>
+                <constraints>
+                    <constraint firstAttribute="bottom" secondItem="Vxp-gw-YTt" secondAttribute="bottom" constant="11" id="0Qz-iR-Tzb"/>
+                    <constraint firstAttribute="centerY" secondItem="Vxp-gw-YTt" secondAttribute="centerY" id="4Vh-2e-m2p"/>
+                    <constraint firstAttribute="centerY" secondItem="yhI-dj-sRk" secondAttribute="centerY" id="Vw4-h8-wId"/>
+                    <constraint firstAttribute="trailingMargin" secondItem="yhI-dj-sRk" secondAttribute="trailing" id="W8E-PI-peE"/>
+                    <constraint firstItem="Vxp-gw-YTt" firstAttribute="top" secondItem="hV6-xt-6pq" secondAttribute="top" constant="11" id="bgO-t8-Rjz"/>
+                    <constraint firstItem="Vxp-gw-YTt" firstAttribute="leading" secondItem="hV6-xt-6pq" secondAttribute="leadingMargin" id="mVS-0p-p0O"/>
+                    <constraint firstItem="yhI-dj-sRk" firstAttribute="leading" secondItem="Vxp-gw-YTt" secondAttribute="trailing" id="n0B-tg-Pik"/>
+                </constraints>
+            </tableViewCellContentView>
+            <connections>
+                <outlet property="rateTitle" destination="Vxp-gw-YTt" id="KRL-Lg-C7F"/>
+                <outlet property="ratingView" destination="yhI-dj-sRk" id="QBD-SA-AlI"/>
+            </connections>
+            <point key="canvasLocation" x="301" y="260"/>
+        </tableViewCell>
+    </objects>
+</document>

+ 13 - 0
Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.h

@@ -0,0 +1,13 @@
+//
+//  FYSectionCell.h
+//  XLForm
+//
+//  Created by 尹彬 on 2017/10/7.
+//  Copyright © 2017年 Xmartlabs. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface FYSectionCell : UITableViewHeaderFooterView
+
+@end

+ 17 - 0
Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.m

@@ -0,0 +1,17 @@
+//
+//  FYSectionCell.m
+//  XLForm
+//
+//  Created by 尹彬 on 2017/10/7.
+//  Copyright © 2017年 Xmartlabs. All rights reserved.
+//
+
+#import "FYSectionCell.h"
+
+@implementation FYSectionCell
+
+- (void)awakeFromNib {
+    [super awakeFromNib];
+    // Initialization code
+}
+@end

+ 41 - 0
Examples/Objective-C/Examples/CustomRows/Section/FYSectionCell.xib

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES">
+    <device id="retina4_7" orientation="portrait">
+        <adaptation id="fullscreen"/>
+    </device>
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
+        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="FYSectionCell" rowHeight="48" id="KGk-i7-Jjw" customClass="FYSectionCell">
+            <rect key="frame" x="0.0" y="0.0" width="320" height="48"/>
+            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
+                <rect key="frame" x="0.0" y="0.0" width="320" height="47.5"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <tabBar contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pDO-la-IR9">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="47.5"/>
+                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
+                        <items>
+                            <tabBarItem systemItem="favorites" id="vVO-5m-ZP5"/>
+                            <tabBarItem systemItem="more" id="I6U-RN-b3b"/>
+                        </items>
+                    </tabBar>
+                </subviews>
+                <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                <constraints>
+                    <constraint firstAttribute="trailing" secondItem="pDO-la-IR9" secondAttribute="trailing" id="KWH-Ys-oz8"/>
+                    <constraint firstItem="pDO-la-IR9" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="top" id="NBM-wu-e5K"/>
+                    <constraint firstAttribute="bottom" secondItem="pDO-la-IR9" secondAttribute="bottom" id="eMi-Ua-gci"/>
+                    <constraint firstItem="pDO-la-IR9" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leading" id="uYF-PG-7al"/>
+                </constraints>
+            </tableViewCellContentView>
+            <point key="canvasLocation" x="-798" y="-239"/>
+        </tableViewCell>
+    </objects>
+</document>

+ 57 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/LxGridViewFlowLayout.h

@@ -0,0 +1,57 @@
+//
+//  LxGridViewFlowLayout.h
+//  LxGridView
+//
+
+#import <UIKit/UIKit.h>
+
+/*
+ 此类来源于DeveloperLx的优秀开源项目:LxGridView
+ github链接:https://github.com/DeveloperLx/LxGridView
+ 我对这个类的代码做了一些修改;
+ 感谢DeveloperLx的优秀代码~
+ */
+
+@interface LxGridViewFlowLayout : UICollectionViewFlowLayout
+
+@property (nonatomic,assign) BOOL panGestureRecognizerEnable;
+
+@end
+
+@protocol LxGridViewDataSource <UICollectionViewDataSource>
+
+@optional
+
+- (void)collectionView:(UICollectionView *)collectionView
+       itemAtIndexPath:(NSIndexPath *)sourceIndexPath
+   willMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
+- (void)collectionView:(UICollectionView *)collectionView
+       itemAtIndexPath:(NSIndexPath *)sourceIndexPath
+    didMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
+
+- (BOOL)collectionView:(UICollectionView *)collectionView
+canMoveItemAtIndexPath:(NSIndexPath *)indexPath;
+- (BOOL)collectionView:(UICollectionView *)collectionView
+       itemAtIndexPath:(NSIndexPath *)sourceIndexPath
+    canMoveToIndexPath:(NSIndexPath *)destinationIndexPath;
+
+@end
+
+@protocol LxGridViewDelegateFlowLayout <UICollectionViewDelegateFlowLayout>
+
+@optional
+
+- (void)collectionView:(UICollectionView *)collectionView
+                layout:(UICollectionViewLayout *)collectionViewLayout
+willBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
+- (void)collectionView:(UICollectionView *)collectionView
+                layout:(UICollectionViewLayout *)collectionViewLayout
+didBeginDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
+- (void)collectionView:(UICollectionView *)collectionView
+                layout:(UICollectionViewLayout *)collectionViewLayout
+willEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
+- (void)collectionView:(UICollectionView *)collectionView
+                layout:(UICollectionViewLayout *)collectionViewLayout
+didEndDraggingItemAtIndexPath:(NSIndexPath *)indexPath;
+
+@end

+ 408 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/LxGridViewFlowLayout.m

@@ -0,0 +1,408 @@
+//
+//  LxGridViewFlowLayout.m
+//  LxGridView
+//
+
+#import "LxGridViewFlowLayout.h"
+#import "TZTestCell.h"
+#import "UIView+Layout.h"
+
+#define stringify   __STRING
+
+static CGFloat const PRESS_TO_MOVE_MIN_DURATION = 0.1;
+static CGFloat const MIN_PRESS_TO_BEGIN_EDITING_DURATION = 0.6;
+
+CG_INLINE CGPoint CGPointOffset(CGPoint point, CGFloat dx, CGFloat dy)
+{
+    return CGPointMake(point.x + dx, point.y + dy);
+}
+
+/*
+ 此类来源于DeveloperLx的优秀开源项目:LxGridView
+ github链接:https://github.com/DeveloperLx/LxGridView
+ 我对这个类的代码做了一些修改;
+ 感谢DeveloperLx的优秀代码~
+ */
+
+@interface LxGridViewFlowLayout () <UIGestureRecognizerDelegate>
+
+@property (nonatomic,readonly) id<LxGridViewDataSource> dataSource;
+@property (nonatomic,readonly) id<LxGridViewDelegateFlowLayout> delegate;
+
+@end
+
+@implementation LxGridViewFlowLayout
+{
+    UILongPressGestureRecognizer * _longPressGestureRecognizer;
+    UIPanGestureRecognizer * _panGestureRecognizer;
+    NSIndexPath * _movingItemIndexPath;
+    UIView * _beingMovedPromptView;
+    CGPoint _sourceItemCollectionViewCellCenter;
+    
+    CADisplayLink * _displayLink;
+    CFTimeInterval _remainSecondsToBeginEditing;
+}
+
+#pragma mark - setup
+
+- (void)dealloc
+{
+    [_displayLink invalidate];
+    
+    [self removeGestureRecognizers];
+    [self removeObserver:self forKeyPath:@stringify(collectionView)];
+}
+
+- (instancetype)init
+{
+    if (self = [super init]) {
+        [self setup];
+    }
+    return self;
+}
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    if (self = [super initWithCoder:coder]) {
+        [self setup];
+    }
+    return self;
+}
+
+- (void)setup
+{
+    [self addObserver:self forKeyPath:@stringify(collectionView) options:NSKeyValueObservingOptionNew context:nil];
+}
+
+- (void)addGestureRecognizers
+{
+    self.collectionView.userInteractionEnabled = YES;
+    
+    _longPressGestureRecognizer = [[UILongPressGestureRecognizer alloc]initWithTarget:self action:@selector(longPressGestureRecognizerTriggerd:)];
+    _longPressGestureRecognizer.cancelsTouchesInView = NO;
+    _longPressGestureRecognizer.minimumPressDuration = PRESS_TO_MOVE_MIN_DURATION;
+    _longPressGestureRecognizer.delegate = self;
+    
+    for (UIGestureRecognizer * gestureRecognizer in self.collectionView.gestureRecognizers) {
+        if ([gestureRecognizer isKindOfClass:[UILongPressGestureRecognizer class]]) {
+            [gestureRecognizer requireGestureRecognizerToFail:_longPressGestureRecognizer];
+        }
+    }
+    
+    [self.collectionView addGestureRecognizer:_longPressGestureRecognizer];
+    
+    _panGestureRecognizer = [[UIPanGestureRecognizer alloc]initWithTarget:self action:@selector(panGestureRecognizerTriggerd:)];
+    _panGestureRecognizer.delegate = self;
+    [self.collectionView addGestureRecognizer:_panGestureRecognizer];
+    
+    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActive:) name:UIApplicationWillResignActiveNotification object:nil];
+}
+
+- (void)removeGestureRecognizers
+{
+    if (_longPressGestureRecognizer) {
+        if (_longPressGestureRecognizer.view) {
+            [_longPressGestureRecognizer.view removeGestureRecognizer:_longPressGestureRecognizer];
+        }
+        _longPressGestureRecognizer = nil;
+    }
+    
+    if (_panGestureRecognizer) {
+        if (_panGestureRecognizer.view) {
+            [_panGestureRecognizer.view removeGestureRecognizer:_panGestureRecognizer];
+        }
+        _panGestureRecognizer = nil;
+    }
+    
+    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIApplicationWillResignActiveNotification object:nil];
+}
+
+#pragma mark - getter and setter implementation
+
+- (id<LxGridViewDataSource>)dataSource
+{
+    return (id<LxGridViewDataSource>)self.collectionView.dataSource;
+}
+
+- (id<LxGridViewDelegateFlowLayout>)delegate
+{
+    return (id<LxGridViewDelegateFlowLayout>)self.collectionView.delegate;
+}
+
+#pragma mark - override UICollectionViewLayout methods
+
+- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
+{
+    NSArray * layoutAttributesForElementsInRect = [super layoutAttributesForElementsInRect:rect];
+    
+    for (UICollectionViewLayoutAttributes * layoutAttributes in layoutAttributesForElementsInRect) {
+        
+        if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
+            layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath];
+        }
+    }
+    return layoutAttributesForElementsInRect;
+}
+
+- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
+{
+    UICollectionViewLayoutAttributes * layoutAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
+    if (layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
+        layoutAttributes.hidden = [layoutAttributes.indexPath isEqual:_movingItemIndexPath];
+    }
+    return layoutAttributes;
+}
+
+#pragma mark - gesture
+
+- (void)setPanGestureRecognizerEnable:(BOOL)panGestureRecognizerEnable
+{
+    _panGestureRecognizer.enabled = panGestureRecognizerEnable;
+}
+
+- (BOOL)panGestureRecognizerEnable
+{
+    return _panGestureRecognizer.enabled;
+}
+
+- (void)longPressGestureRecognizerTriggerd:(UILongPressGestureRecognizer *)longPress
+{
+    switch (longPress.state) {
+        case UIGestureRecognizerStatePossible:
+            break;
+        case UIGestureRecognizerStateBegan:
+        {
+            if (_displayLink == nil) {
+                _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkTriggered:)];
+                _displayLink.frameInterval = 6;
+                [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
+                
+                _remainSecondsToBeginEditing = MIN_PRESS_TO_BEGIN_EDITING_DURATION;
+            }
+
+            _movingItemIndexPath = [self.collectionView indexPathForItemAtPoint:[longPress locationInView:self.collectionView]];
+            if ([self.dataSource respondsToSelector:@selector(collectionView:canMoveItemAtIndexPath:)] && [self.dataSource collectionView:self.collectionView canMoveItemAtIndexPath:_movingItemIndexPath] == NO) {
+                _movingItemIndexPath = nil;
+                return;
+            }
+            
+            if ([self.delegate respondsToSelector:@selector(collectionView:layout:willBeginDraggingItemAtIndexPath:)]) {
+                [self.delegate collectionView:self.collectionView layout:self willBeginDraggingItemAtIndexPath:_movingItemIndexPath];
+            }
+            
+            UICollectionViewCell *sourceCollectionViewCell = [self.collectionView cellForItemAtIndexPath:_movingItemIndexPath];
+            TZTestCell *sourceCell = (TZTestCell *)sourceCollectionViewCell;
+            
+            _beingMovedPromptView = [[UIView alloc]initWithFrame:CGRectOffset(sourceCollectionViewCell.frame, -10, -10)];
+            _beingMovedPromptView.tz_width += 20;
+            _beingMovedPromptView.tz_height += 20;
+            
+            sourceCollectionViewCell.highlighted = YES;
+            UIView * highlightedSnapshotView = [sourceCell snapshotView];
+            highlightedSnapshotView.frame = _beingMovedPromptView.bounds;
+            highlightedSnapshotView.alpha = 1;
+
+            sourceCollectionViewCell.highlighted = NO;
+            UIView * snapshotView = [sourceCell snapshotView];
+            snapshotView.frame = _beingMovedPromptView.bounds;
+            snapshotView.alpha = 0;
+            
+            [_beingMovedPromptView addSubview:snapshotView];
+            [_beingMovedPromptView addSubview:highlightedSnapshotView];
+            [self.collectionView addSubview:_beingMovedPromptView];
+
+             _sourceItemCollectionViewCellCenter = sourceCollectionViewCell.center;
+            
+            typeof(self) __weak weakSelf = self;
+            [UIView animateWithDuration:0
+                                  delay:0
+                                options:UIViewAnimationOptionBeginFromCurrentState
+                             animations:^{
+
+                                 typeof(self) __strong strongSelf = weakSelf;
+                                 if (strongSelf) {
+                                     highlightedSnapshotView.alpha = 0;
+                                     snapshotView.alpha = 1;
+                                 }
+                             }
+                             completion:^(BOOL finished) {
+                                 
+                                 typeof(self) __strong strongSelf = weakSelf;
+                                 if (strongSelf) {
+                                     [highlightedSnapshotView removeFromSuperview];
+                                     
+                                     if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didBeginDraggingItemAtIndexPath:)]) {
+                                         [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didBeginDraggingItemAtIndexPath:_movingItemIndexPath];
+                                     }
+                                 }
+                             }];
+             
+            [self invalidateLayout];
+        }
+            break;
+        case UIGestureRecognizerStateChanged:
+            break;
+        case UIGestureRecognizerStateEnded:
+        case UIGestureRecognizerStateCancelled:
+        {
+            [_displayLink invalidate];
+            _displayLink = nil;
+            
+            NSIndexPath * movingItemIndexPath = _movingItemIndexPath;
+            
+            if (movingItemIndexPath) {
+                if ([self.delegate respondsToSelector:@selector(collectionView:layout:willEndDraggingItemAtIndexPath:)]) {
+                    [self.delegate collectionView:self.collectionView layout:self willEndDraggingItemAtIndexPath:movingItemIndexPath];
+                }
+                
+                _movingItemIndexPath = nil;
+                _sourceItemCollectionViewCellCenter = CGPointZero;
+                
+                UICollectionViewLayoutAttributes * movingItemCollectionViewLayoutAttributes = [self layoutAttributesForItemAtIndexPath:movingItemIndexPath];
+                
+                _longPressGestureRecognizer.enabled = NO;
+                
+                typeof(self) __weak weakSelf = self;
+                [UIView animateWithDuration:0.2
+                                      delay:0
+                                    options:UIViewAnimationOptionBeginFromCurrentState
+                                 animations:^{
+                                     typeof(self) __strong strongSelf = weakSelf;
+                                     if (strongSelf) {
+                                         _beingMovedPromptView.center = movingItemCollectionViewLayoutAttributes.center;
+                                     }
+                                 }
+                                 completion:^(BOOL finished) {
+
+                                     _longPressGestureRecognizer.enabled = YES;
+                                     
+                                     typeof(self) __strong strongSelf = weakSelf;
+                                     if (strongSelf) {
+                                         [_beingMovedPromptView removeFromSuperview];
+                                         _beingMovedPromptView = nil;
+                                         [strongSelf invalidateLayout];
+                                         
+                                         if ([strongSelf.delegate respondsToSelector:@selector(collectionView:layout:didEndDraggingItemAtIndexPath:)]) {
+                                             [strongSelf.delegate collectionView:strongSelf.collectionView layout:strongSelf didEndDraggingItemAtIndexPath:movingItemIndexPath];
+                                         }
+                                     }
+                                 }];
+            }
+        }
+            break;
+        case UIGestureRecognizerStateFailed:
+            break;
+        default:
+            break;
+    }
+}
+
+- (void)panGestureRecognizerTriggerd:(UIPanGestureRecognizer *)pan
+{
+    switch (pan.state) {
+        case UIGestureRecognizerStatePossible:
+            break;
+        case UIGestureRecognizerStateBegan:
+        case UIGestureRecognizerStateChanged:
+        {
+            CGPoint panTranslation = [pan translationInView:self.collectionView];
+            _beingMovedPromptView.center = CGPointOffset(_sourceItemCollectionViewCellCenter, panTranslation.x, panTranslation.y);
+            
+            NSIndexPath * sourceIndexPath = _movingItemIndexPath;
+            NSIndexPath * destinationIndexPath = [self.collectionView indexPathForItemAtPoint:_beingMovedPromptView.center];
+            
+            if ((destinationIndexPath == nil) || [destinationIndexPath isEqual:sourceIndexPath]) {
+                return;
+            }
+            
+            if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:canMoveToIndexPath:)] && [self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath canMoveToIndexPath:destinationIndexPath] == NO) {
+                return;
+            }
+            
+            if ([self.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:willMoveToIndexPath:)]) {
+                [self.dataSource collectionView:self.collectionView itemAtIndexPath:sourceIndexPath willMoveToIndexPath:destinationIndexPath];
+            }
+            
+            _movingItemIndexPath = destinationIndexPath;
+            
+            typeof(self) __weak weakSelf = self;
+            [self.collectionView performBatchUpdates:^{
+                typeof(self) __strong strongSelf = weakSelf;
+                if (strongSelf) {
+                    if (sourceIndexPath && destinationIndexPath) {
+                        [strongSelf.collectionView deleteItemsAtIndexPaths:@[sourceIndexPath]];
+                        [strongSelf.collectionView insertItemsAtIndexPaths:@[destinationIndexPath]];
+                    }
+                }
+            } completion:^(BOOL finished) {
+                typeof(self) __strong strongSelf = weakSelf;
+                if ([strongSelf.dataSource respondsToSelector:@selector(collectionView:itemAtIndexPath:didMoveToIndexPath:)]) {
+                    [strongSelf.dataSource collectionView:strongSelf.collectionView itemAtIndexPath:sourceIndexPath didMoveToIndexPath:destinationIndexPath];
+                }
+            }];
+        }
+            break;
+        case UIGestureRecognizerStateEnded:
+            break;
+        case UIGestureRecognizerStateCancelled:
+            break;
+        case UIGestureRecognizerStateFailed:
+            break;
+        default:
+            break;
+    }
+}
+
+- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
+{
+    if ([_panGestureRecognizer isEqual:gestureRecognizer]) {
+        return _movingItemIndexPath != nil;
+    }
+    return YES;
+}
+
+- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
+{
+    //  only _longPressGestureRecognizer and _panGestureRecognizer can recognize simultaneously
+    if ([_longPressGestureRecognizer isEqual:gestureRecognizer]) {
+        return [_panGestureRecognizer isEqual:otherGestureRecognizer];
+    }
+    if ([_panGestureRecognizer isEqual:gestureRecognizer]) {
+        return [_longPressGestureRecognizer isEqual:otherGestureRecognizer];
+    }
+    return NO;
+}
+
+#pragma mark - displayLink
+
+- (void)displayLinkTriggered:(CADisplayLink *)displayLink
+{
+    if (_remainSecondsToBeginEditing <= 0) {
+        [_displayLink invalidate];
+        _displayLink = nil;
+    }
+    
+    _remainSecondsToBeginEditing = _remainSecondsToBeginEditing - 0.1;
+}
+
+#pragma mark - KVO and notification
+
+- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    if ([keyPath isEqualToString:@stringify(collectionView)]) {
+        if (self.collectionView) {
+            [self addGestureRecognizers];
+        }
+        else {
+            [self removeGestureRecognizers];
+        }
+    }
+}
+
+- (void)applicationWillResignActive:(NSNotification *)notificaiton
+{
+    _panGestureRecognizer.enabled = NO;
+    _panGestureRecognizer.enabled = YES;
+}
+
+@end

+ 17 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZPhotoCell.h

@@ -0,0 +1,17 @@
+//
+//  ViewController.h
+//  TZImagePickerController
+//
+//  Created by 尹彬 on 17/10/7.
+//  Copyright © 2017年 尹彬. All rights reserved.
+//
+
+#import "XLFormBaseCell.h"
+
+extern NSString * const XLFormRowDescriptorTypePhotoView;
+
+@interface TZPhotoCell : XLFormBaseCell
+
+
+@end
+

+ 624 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZPhotoCell.m

@@ -0,0 +1,624 @@
+//
+//  ViewController.m
+//  TZImagePickerController
+//
+//  Created by 尹彬 on 17/10/7.
+//  Copyright © 2017年 尹彬. All rights reserved.
+//
+
+#import "TZPhotoCell.h"
+#import "TZImagePickerController.h"
+#import "UIView+Layout.h"
+#import "TZTestCell.h"
+#import <AssetsLibrary/AssetsLibrary.h>
+#import <Photos/Photos.h>
+#import "LxGridViewFlowLayout.h"
+#import "TZImageManager.h"
+#import "TZVideoPlayerController.h"
+#import "TZPhotoPreviewController.h"
+#import "TZGifPhotoPreviewController.h"
+#import "TZLocationManager.h"
+
+
+NSString * const XLFormRowDescriptorTypePhotoView = @"XLFormRowDescriptorTypePhotoView";
+
+@interface TZPhotoCell ()< TZImagePickerControllerDelegate,UICollectionViewDataSource,UICollectionViewDelegate,UIActionSheetDelegate,UIImagePickerControllerDelegate,UIAlertViewDelegate,UINavigationControllerDelegate> {
+    NSMutableArray *_selectedPhotos;
+    NSMutableArray *_selectedAssets;
+    BOOL _isSelectOriginalPhoto;
+    
+    CGFloat _itemWH;
+    CGFloat _margin;
+}
+@property (nonatomic, strong) UIImagePickerController *imagePickerVc;
+@property (nonatomic, strong) UICollectionView        *collectionView;
+@property (strong, nonatomic) LxGridViewFlowLayout    *layout;
+@property (strong, nonatomic) CLLocation              *location;
+
+@end
+
+@implementation TZPhotoCell
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:NSStringFromClass([TZPhotoCell class]) forKey:XLFormRowDescriptorTypePhotoView];
+}
+
+- (void)configure
+{
+    [super configure];
+    
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    //    [self.ratingView addTarget:self action:@selector(rateChanged:) forControlEvents:UIControlEventValueChanged];
+    
+    // Do any additional setup after loading the view, typically from a nib.
+    self.contentView.backgroundColor = [UIColor whiteColor];
+    _selectedPhotos                  = [NSMutableArray array];
+    _selectedAssets                  = [NSMutableArray array];
+    [self configCollectionView];
+}
+
+- (void)update
+{
+    [super update];
+    
+    //    self.ratingView.value = [self.rowDescriptor.value floatValue];
+    //    self.rateTitle.text   = self.rowDescriptor.title;
+}
+
+
++(CGFloat)formDescriptorCellHeightForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor {
+    return 210;
+}
+
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+- (UIImagePickerController *)imagePickerVc {
+    if (_imagePickerVc == nil) {
+        _imagePickerVc          = [[UIImagePickerController alloc] init];
+        _imagePickerVc.delegate = self;
+        UIBarButtonItem *tzBarItem, *BarItem;
+        if (iOS9Later) {
+            tzBarItem = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[TZImagePickerController class]]];
+            BarItem   = [UIBarButtonItem appearanceWhenContainedInInstancesOfClasses:@[[UIImagePickerController class]]];
+        } else {
+            tzBarItem = [UIBarButtonItem appearanceWhenContainedIn:[TZImagePickerController class], nil];
+            BarItem   = [UIBarButtonItem appearanceWhenContainedIn:[UIImagePickerController class], nil];
+        }
+        NSDictionary *titleTextAttributes = [tzBarItem titleTextAttributesForState:UIControlStateNormal];
+        [BarItem setTitleTextAttributes:titleTextAttributes forState:UIControlStateNormal];
+        
+    }
+    return _imagePickerVc;
+}
+
+- (BOOL)prefersStatusBarHidden {
+    return NO;
+}
+
+- (void)configCollectionView {
+    
+    
+    // 如不需要长按排序效果,将LxGridViewFlowLayout类改成UICollectionViewFlowLayout即可
+    _layout                              = [[LxGridViewFlowLayout alloc] init];
+    _collectionView                      = [[UICollectionView alloc] initWithFrame:CGRectZero collectionViewLayout:_layout];
+    CGFloat rgb                          = 244 / 255.0;
+    _collectionView.alwaysBounceVertical = YES;
+    _collectionView.backgroundColor      = [UIColor colorWithRed:rgb green:rgb blue:rgb alpha:1.0];
+    _collectionView.contentInset         = UIEdgeInsetsMake(4, 4, 4, 4);
+    _collectionView.dataSource           = self;
+    _collectionView.delegate             = self;
+    _collectionView.keyboardDismissMode  = UIScrollViewKeyboardDismissModeOnDrag;
+    [self.contentView addSubview:_collectionView];
+    [_collectionView registerClass:[TZTestCell class] forCellWithReuseIdentifier:@"TZTestCell"];
+    
+    _collectionView.bounces                        = NO;
+    _collectionView.showsVerticalScrollIndicator   = NO;
+    _collectionView.showsHorizontalScrollIndicator = NO;
+    [self viewDidLayoutSubviews];
+}
+
+- (void)viewDidLayoutSubviews {
+    NSInteger contentSizeH = 0;
+    //    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.01 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
+    //        self.scrollView.contentSize = CGSizeMake(0, contentSizeH + 5);
+    //    });
+    
+    CGSize size    = [UIScreen mainScreen].bounds.size;
+    CGFloat height = 210;
+    
+    _margin                         = 4;
+    _itemWH                         = (size.width - 2 * _margin - 4) / 3 - _margin;
+    _layout.itemSize                = CGSizeMake(_itemWH, _itemWH);
+    _layout.minimumInteritemSpacing = _margin;
+    _layout.minimumLineSpacing      = _margin;
+    [self.collectionView setCollectionViewLayout:_layout];
+    self.collectionView.frame = CGRectMake(0, contentSizeH, size.width, height - contentSizeH);
+}
+
+#pragma mark UICollectionView
+
+- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
+    return _selectedPhotos.count + 1;
+}
+
+- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
+    TZTestCell *cell           = [collectionView dequeueReusableCellWithReuseIdentifier:@"TZTestCell" forIndexPath:indexPath];
+    cell.videoImageView.hidden = YES;
+    if (indexPath.row == _selectedPhotos.count) {
+        cell.imageView.image       = [UIImage imageNamed:@"AlbumAddBtn.png"];
+        cell.deleteBtn.hidden      = YES;
+        cell.gifLable.hidden       = YES;
+    } else {
+        cell.imageView.image  = _selectedPhotos[indexPath.row];
+        cell.asset            = _selectedAssets[indexPath.row];
+        cell.deleteBtn.hidden = NO;
+    }
+    cell.gifLable.hidden = YES;
+    cell.deleteBtn.tag   = indexPath.row;
+    [cell.deleteBtn addTarget:self action:@selector(deleteBtnClik:) forControlEvents:UIControlEventTouchUpInside];
+    return cell;
+}
+
+- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
+    if (indexPath.row == _selectedPhotos.count) {
+        BOOL showSheet = YES;
+        if (showSheet) {
+            UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:nil delegate:self cancelButtonTitle:@"取消" destructiveButtonTitle:nil otherButtonTitles:@"拍照",@"去相册选择", nil];
+            [sheet showInView:self.formViewController.view];
+        } else {
+            [self pushTZImagePickerController];
+        }
+    } else { // preview photos or video / 预览照片或者视频
+        id asset     = _selectedAssets[indexPath.row];
+        BOOL isVideo = NO;
+        if ([asset isKindOfClass:[PHAsset class]]) {
+            PHAsset *phAsset = asset;
+            isVideo          = phAsset.mediaType == PHAssetMediaTypeVideo;
+        } else if ([asset isKindOfClass:[ALAsset class]]) {
+            ALAsset *alAsset = asset;
+            isVideo          = [[alAsset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo];
+        }
+        if ([[asset valueForKey:@"filename"] tz_containsString:@"GIF"] ) {
+            TZGifPhotoPreviewController *vc = [[TZGifPhotoPreviewController alloc] init];
+            TZAssetModel *model             = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypePhotoGif timeLength:@""];
+            vc.model                        = model;
+            [self.formViewController presentViewController:vc animated:YES completion:nil];
+        } else if (isVideo ) { // perview video / 预览视频
+            TZVideoPlayerController *vc = [[TZVideoPlayerController alloc] init];
+            TZAssetModel *model         = [TZAssetModel modelWithAsset:asset type:TZAssetModelMediaTypeVideo timeLength:@""];
+            vc.model                    = model;
+            
+            [self.formViewController presentViewController:vc animated:YES completion:nil];
+        } else { // preview photos / 预览照片
+            TZImagePickerController *imagePickerVc  = [[TZImagePickerController alloc] initWithSelectedAssets:_selectedAssets selectedPhotos:_selectedPhotos index:indexPath.row];
+            imagePickerVc.maxImagesCount            = 5;
+            imagePickerVc.allowPickingGif           = NO;
+            imagePickerVc.allowPickingOriginalPhoto = YES;
+            imagePickerVc.allowPickingMultipleVideo = NO;
+            imagePickerVc.isSelectOriginalPhoto     = _isSelectOriginalPhoto;
+            [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
+                _selectedPhotos        = [NSMutableArray arrayWithArray:photos];
+                _selectedAssets        = [NSMutableArray arrayWithArray:assets];
+                _isSelectOriginalPhoto = isSelectOriginalPhoto;
+                [_collectionView reloadData];
+                _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
+            }];
+            [self.formViewController presentViewController:imagePickerVc animated:YES completion:nil];
+        }
+    }
+}
+
+#pragma mark - LxGridViewDataSource
+
+/// 以下三个方法为长按排序相关代码
+- (BOOL)collectionView:(UICollectionView *)collectionView canMoveItemAtIndexPath:(NSIndexPath *)indexPath {
+    return indexPath.item < _selectedPhotos.count;
+}
+
+- (BOOL)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)sourceIndexPath canMoveToIndexPath:(NSIndexPath *)destinationIndexPath {
+    return (sourceIndexPath.item < _selectedPhotos.count && destinationIndexPath.item < _selectedPhotos.count);
+}
+
+- (void)collectionView:(UICollectionView *)collectionView itemAtIndexPath:(NSIndexPath *)sourceIndexPath didMoveToIndexPath:(NSIndexPath *)destinationIndexPath {
+    UIImage *image = _selectedPhotos[sourceIndexPath.item];
+    [_selectedPhotos removeObjectAtIndex:sourceIndexPath.item];
+    [_selectedPhotos insertObject:image atIndex:destinationIndexPath.item];
+    
+    id asset = _selectedAssets[sourceIndexPath.item];
+    [_selectedAssets removeObjectAtIndex:sourceIndexPath.item];
+    [_selectedAssets insertObject:asset atIndex:destinationIndexPath.item];
+    
+    [_collectionView reloadData];
+}
+
+#pragma mark - TZImagePickerController
+
+- (void)pushTZImagePickerController {
+    TZImagePickerController *imagePickerVc = [[TZImagePickerController alloc] initWithMaxImagesCount:5 columnNumber:2 delegate:self pushPhotoPickerVc:YES];
+    // imagePickerVc.navigationBar.translucent = NO;
+    
+#pragma mark - 五类个性化设置,这些参数都可以不传,此时会走默认设置
+    imagePickerVc.isSelectOriginalPhoto = _isSelectOriginalPhoto;
+    
+    // 1.设置目前已经选中的图片数组
+    imagePickerVc.selectedAssets   = _selectedAssets;// 目前已经选中的图片数组
+    imagePickerVc.allowTakePicture = NO;// 在内部显示拍照按钮
+    
+    // imagePickerVc.photoWidth = 1000;
+    
+    // 2. Set the appearance
+    // 2. 在这里设置imagePickerVc的外观
+    // imagePickerVc.navigationBar.barTintColor = [UIColor greenColor];
+    // imagePickerVc.oKButtonTitleColorDisabled = [UIColor lightGrayColor];
+    // imagePickerVc.oKButtonTitleColorNormal = [UIColor greenColor];
+    // imagePickerVc.navigationBar.translucent = NO;
+    
+    // 3. Set allow picking video & photo & originalPhoto or not
+    // 3. 设置是否可以选择视频/图片/原图
+    imagePickerVc.allowPickingVideo         = NO;
+    imagePickerVc.allowPickingImage         = YES;
+    imagePickerVc.allowPickingOriginalPhoto = YES;
+    imagePickerVc.allowPickingGif           = NO;
+    imagePickerVc.allowPickingMultipleVideo = NO;// 是否可以多选视频
+    
+    // 4. 照片排列按修改时间升序
+    imagePickerVc.sortAscendingByModificationDate = YES;
+    
+    // imagePickerVc.minImagesCount = 3;
+    // imagePickerVc.alwaysEnableDoneBtn = YES;
+    
+    // imagePickerVc.minPhotoWidthSelectable = 3000;
+    // imagePickerVc.minPhotoHeightSelectable = 2000;
+    
+    /// 5. Single selection mode, valid when maxImagesCount = 1
+    /// 5. 单选模式,maxImagesCount为1时才生效
+    imagePickerVc.showSelectBtn  = NO;
+    imagePickerVc.allowCrop      = NO;
+    imagePickerVc.needCircleCrop = NO;
+    // 设置竖屏下的裁剪尺寸
+    NSInteger left         = 30;
+    NSInteger widthHeight  = self.contentView.tz_width - 2 * left;
+    NSInteger top          = (self.contentView.tz_height - widthHeight) / 2;
+    imagePickerVc.cropRect = CGRectMake(left, top, widthHeight, widthHeight);
+    // 设置横屏下的裁剪尺寸
+    // imagePickerVc.cropRectLandscape = CGRectMake((self.view.tz_height - widthHeight) / 2, left, widthHeight, widthHeight);
+    /*
+     [imagePickerVc setCropViewSettingBlock:^(UIView *cropView) {
+     cropView.layer.borderColor = [UIColor redColor].CGColor;
+     cropView.layer.borderWidth = 2.0;
+     }];*/
+    
+    //imagePickerVc.allowPreview = NO;
+    // 自定义导航栏上的返回按钮
+    /*
+     [imagePickerVc setNavLeftBarButtonSettingBlock:^(UIButton *leftButton){
+     [leftButton setImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
+     [leftButton setImageEdgeInsets:UIEdgeInsetsMake(0, -20, 0, 20)];
+     }];
+     imagePickerVc.delegate = self;
+     */
+    
+    imagePickerVc.isStatusBarDefault = NO;
+#pragma mark - 到这里为止
+    
+    // You can get the photos by block, the same as by delegate.
+    // 你可以通过block或者代理,来得到用户选择的照片.
+    [imagePickerVc setDidFinishPickingPhotosHandle:^(NSArray<UIImage *> *photos, NSArray *assets, BOOL isSelectOriginalPhoto) {
+        
+    }];
+    
+    [self.formViewController presentViewController:imagePickerVc animated:YES completion:nil];
+}
+
+/*
+ // 设置了navLeftBarButtonSettingBlock后,需打开这个方法,让系统的侧滑返回生效
+ - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
+ 
+ navigationController.interactivePopGestureRecognizer.enabled  = YES;
+ if (viewController != navigationController.viewControllers[0]) {
+ navigationController.interactivePopGestureRecognizer.delegate = nil;// 支持侧滑
+ }
+ }
+ */
+
+#pragma mark - UIImagePickerController
+
+- (void)takePhoto {
+    AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
+    if ((authStatus == AVAuthorizationStatusRestricted || authStatus == AVAuthorizationStatusDenied) && iOS7Later) {
+        // 无相机权限 做一个友好的提示
+        if (iOS8Later) {
+            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
+            [alert show];
+        } else {
+            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法使用相机" message:@"请在iPhone的""设置-隐私-相机""中允许访问相机" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
+            [alert show];
+        }
+    } else if (authStatus == AVAuthorizationStatusNotDetermined) {
+        // fix issue 466, 防止用户首次拍照拒绝授权时相机页黑屏
+        if (iOS7Later) {
+            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
+                if (granted) {
+                    dispatch_sync(dispatch_get_main_queue(), ^{
+                        [self takePhoto];
+                    });
+                }
+            }];
+        } else {
+            [self takePhoto];
+        }
+        // 拍照之前还需要检查相册权限
+    } else if ([TZImageManager authorizationStatus] == 2) { // 已被拒绝,没有相册权限,将无法保存拍的照片
+        if (iOS8Later) {
+            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"设置", nil];
+            [alert show];
+        } else {
+            UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"无法访问相册" message:@"请在iPhone的""设置-隐私-相册""中允许访问相册" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:nil];
+            [alert show];
+        }
+    } else if ([TZImageManager authorizationStatus] == 0) { // 未请求过相册权限
+        [[TZImageManager manager] requestAuthorizationWithCompletion:^{
+            [self takePhoto];
+        }];
+    } else {
+        [self pushImagePickerController];
+    }
+}
+
+// 调用相机
+- (void)pushImagePickerController {
+    // 提前定位
+    __weak typeof(self) weakSelf = self;
+    [[TZLocationManager manager] startLocationWithSuccessBlock:^(CLLocation *location, CLLocation *oldLocation) {
+        weakSelf.location = location;
+    } failureBlock:^(NSError *error) {
+        weakSelf.location = nil;
+    }];
+    
+    UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypeCamera;
+    if ([UIImagePickerController isSourceTypeAvailable: UIImagePickerControllerSourceTypeCamera]) {
+        self.imagePickerVc.sourceType = sourceType;
+        if(iOS8Later) {
+            _imagePickerVc.modalPresentationStyle = UIModalPresentationOverCurrentContext;
+        }
+        [self.formViewController presentViewController:_imagePickerVc animated:YES completion:nil];
+    } else {
+        NSLog(@"模拟器中无法打开照相机,请在真机中使用");
+    }
+}
+
+- (void)imagePickerController:(UIImagePickerController*)picker didFinishPickingMediaWithInfo:(NSDictionary *)info {
+    [picker dismissViewControllerAnimated:YES completion:nil];
+    NSString *type = [info objectForKey:UIImagePickerControllerMediaType];
+    if ([type isEqualToString:@"public.image"]) {
+        TZImagePickerController *tzImagePickerVc        = [[TZImagePickerController alloc] initWithMaxImagesCount:1 delegate:self];
+        tzImagePickerVc.sortAscendingByModificationDate = YES;
+        [tzImagePickerVc showProgressHUD];
+        UIImage *image = [info objectForKey:UIImagePickerControllerOriginalImage];
+        
+        // save photo and get asset / 保存图片,获取到asset
+        [[TZImageManager manager] savePhotoWithImage:image location:self.location completion:^(NSError *error){
+            if (error) {
+                [tzImagePickerVc hideProgressHUD];
+                NSLog(@"图片保存失败 %@",error);
+            } else {
+                [[TZImageManager manager] getCameraRollAlbum:NO allowPickingImage:YES completion:^(TZAlbumModel *model) {
+                    [[TZImageManager manager] getAssetsFromFetchResult:model.result allowPickingVideo:NO allowPickingImage:YES completion:^(NSArray<TZAssetModel *> *models) {
+                        [tzImagePickerVc hideProgressHUD];
+                        TZAssetModel *assetModel = [models firstObject];
+                        if (tzImagePickerVc.sortAscendingByModificationDate) {
+                            assetModel = [models lastObject];
+                        }
+                        //                        if (NO) { // 允许裁剪,去裁剪
+                        //                            TZImagePickerController *imagePicker = [[TZImagePickerController alloc] initCropTypeWithAsset:assetModel.asset photo:image completion:^(UIImage *cropImage, id asset) {
+                        //                                [self refreshCollectionViewWithAddedAsset:asset image:cropImage];
+                        //                            }];
+                        //                            imagePicker.needCircleCrop   = self.needCircleCropSwitch.isOn;
+                        //                            imagePicker.circleCropRadius = 100;
+                        //                            [self presentViewController:imagePicker animated:YES completion:nil];
+                        //                        } else {
+                        [self refreshCollectionViewWithAddedAsset:assetModel.asset image:image];
+                        //                        }
+                    }];
+                }];
+            }
+        }];
+    }
+}
+
+- (void)refreshCollectionViewWithAddedAsset:(id)asset image:(UIImage *)image {
+    [_selectedAssets addObject:asset];
+    [_selectedPhotos addObject:image];
+    [_collectionView reloadData];
+    
+    if ([asset isKindOfClass:[PHAsset class]]) {
+        PHAsset *phAsset = asset;
+        NSLog(@"location:%@",phAsset.location);
+    }
+}
+
+- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker {
+    if ([picker isKindOfClass:[UIImagePickerController class]]) {
+        [picker dismissViewControllerAnimated:YES completion:nil];
+    }
+}
+
+#pragma mark - UIActionSheetDelegate
+
+- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
+    if (buttonIndex == 0) { // take photo / 去拍照
+        [self takePhoto];
+    } else if (buttonIndex == 1) {
+        [self pushTZImagePickerController];
+    }
+}
+
+#pragma mark - UIAlertViewDelegate
+
+- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
+    if (buttonIndex == 1) { // 去设置界面,开启相机访问权限
+        if (iOS8Later) {
+            [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];
+        }
+    }
+}
+
+#pragma mark - TZImagePickerControllerDelegate
+
+/// User click cancel button
+/// 用户点击了取消
+- (void)tz_imagePickerControllerDidCancel:(TZImagePickerController *)picker {
+    // NSLog(@"cancel");
+}
+
+// The picker should dismiss itself; when it dismissed these handle will be called.
+// If isOriginalPhoto is YES, user picked the original photo.
+// You can get original photo with asset, by the method [[TZImageManager manager] getOriginalPhotoWithAsset:completion:].
+// The UIImage Object in photos default width is 828px, you can set it by photoWidth property.
+// 这个照片选择器会自己dismiss,当选择器dismiss的时候,会执行下面的代理方法
+// 如果isSelectOriginalPhoto为YES,表明用户选择了原图
+// 你可以通过一个asset获得原图,通过这个方法:[[TZImageManager manager] getOriginalPhotoWithAsset:completion:]
+// photos数组里的UIImage对象,默认是828像素宽,你可以通过设置photoWidth属性的值来改变它
+- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingPhotos:(NSArray *)photos sourceAssets:(NSArray *)assets isSelectOriginalPhoto:(BOOL)isSelectOriginalPhoto {
+    _selectedPhotos        = [NSMutableArray arrayWithArray:photos];
+    _selectedAssets        = [NSMutableArray arrayWithArray:assets];
+    _isSelectOriginalPhoto = isSelectOriginalPhoto;
+    [_collectionView reloadData];
+    // _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
+    
+    // 1.打印图片名字
+    [self printAssetsName:assets];
+    // 2.图片位置信息
+    if (iOS8Later) {
+        for (PHAsset *phAsset in assets) {
+            NSLog(@"location:%@",phAsset.location);
+        }
+    }
+}
+
+// If user picking a video, this callback will be called.
+// If system version > iOS8,asset is kind of PHAsset class, else is ALAsset class.
+// 如果用户选择了一个视频,下面的handle会被执行
+// 如果系统版本大于iOS8,asset是PHAsset类的对象,否则是ALAsset类的对象
+- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingVideo:(UIImage *)coverImage sourceAssets:(id)asset {
+    _selectedPhotos = [NSMutableArray arrayWithArray:@[coverImage]];
+    _selectedAssets = [NSMutableArray arrayWithArray:@[asset]];
+    // open this code to send video / 打开这段代码发送视频
+    // [[TZImageManager manager] getVideoOutputPathWithAsset:asset completion:^(NSString *outputPath) {
+    // NSLog(@"视频导出到本地完成,沙盒路径为:%@",outputPath);
+    // Export completed, send video here, send by outputPath or NSData
+    // 导出完成,在这里写上传代码,通过路径或者通过NSData上传
+    
+    // }];
+    [_collectionView reloadData];
+    // _collectionView.contentSize = CGSizeMake(0, ((_selectedPhotos.count + 2) / 3 ) * (_margin + _itemWH));
+}
+
+// If user picking a gif image, this callback will be called.
+// 如果用户选择了一个gif图片,下面的handle会被执行
+- (void)imagePickerController:(TZImagePickerController *)picker didFinishPickingGifImage:(UIImage *)animatedImage sourceAssets:(id)asset {
+    _selectedPhotos = [NSMutableArray arrayWithArray:@[animatedImage]];
+    _selectedAssets = [NSMutableArray arrayWithArray:@[asset]];
+    [_collectionView reloadData];
+}
+
+// Decide album show or not't
+// 决定相册显示与否
+- (BOOL)isAlbumCanSelect:(NSString *)albumName result:(id)result {
+    /*
+     if ([albumName isEqualToString:@"个人收藏"]) {
+     return NO;
+     }
+     if ([albumName isEqualToString:@"视频"]) {
+     return NO;
+     }*/
+    return YES;
+}
+
+// Decide asset show or not't
+// 决定asset显示与否
+- (BOOL)isAssetCanSelect:(id)asset {
+    /*
+     if (iOS8Later) {
+     PHAsset *phAsset = asset;
+     switch (phAsset.mediaType) {
+     case PHAssetMediaTypeVideo: {
+     // 视频时长
+     // NSTimeInterval duration = phAsset.duration;
+     return NO;
+     } break;
+     case PHAssetMediaTypeImage: {
+     // 图片尺寸
+     if (phAsset.pixelWidth > 3000 || phAsset.pixelHeight > 3000) {
+     // return NO;
+     }
+     return YES;
+     } break;
+     case PHAssetMediaTypeAudio:
+     return NO;
+     break;
+     case PHAssetMediaTypeUnknown:
+     return NO;
+     break;
+     default: break;
+     }
+     } else {
+     ALAsset *alAsset      = asset;
+     NSString *alAssetType = [[alAsset valueForProperty:ALAssetPropertyType] stringValue];
+     if ([alAssetType isEqualToString:ALAssetTypeVideo]) {
+     // 视频时长
+     // NSTimeInterval duration = [[alAsset valueForProperty:ALAssetPropertyDuration] doubleValue];
+     return NO;
+     } else if ([alAssetType isEqualToString:ALAssetTypePhoto]) {
+     // 图片尺寸
+     CGSize imageSize = alAsset.defaultRepresentation.dimensions;
+     if (imageSize.width > 3000) {
+     // return NO;
+     }
+     return YES;
+     } else if ([alAssetType isEqualToString:ALAssetTypeUnknown]) {
+     return NO;
+     }
+     }*/
+    return YES;
+}
+
+#pragma mark - Click Event
+
+- (void)deleteBtnClik:(UIButton *)sender {
+    [_selectedPhotos removeObjectAtIndex:sender.tag];
+    [_selectedAssets removeObjectAtIndex:sender.tag];
+    
+    [_collectionView performBatchUpdates:^{
+        NSIndexPath *indexPath = [NSIndexPath indexPathForItem:sender.tag inSection:0];
+        [_collectionView deleteItemsAtIndexPaths:@[indexPath]];
+    } completion:^(BOOL finished) {
+        [_collectionView reloadData];
+    }];
+}
+
+- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
+    [self.contentView endEditing:YES];
+}
+
+#pragma mark - Private
+
+/// 打印图片名字
+- (void)printAssetsName:(NSArray *)assets {
+    NSString *fileName;
+    for (id asset in assets) {
+        if ([asset isKindOfClass:[PHAsset class]]) {
+            PHAsset *phAsset = (PHAsset *)asset;
+            fileName         = [phAsset valueForKey:@"filename"];
+        } else if ([asset isKindOfClass:[ALAsset class]]) {
+            ALAsset *alAsset = (ALAsset *)asset;
+            fileName         = alAsset.defaultRepresentation.filename;;
+        }
+        // NSLog(@"图片名字:%@",fileName);
+    }
+}
+
+#pragma clang diagnostic pop
+
+@end

+ 23 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZTestCell.h

@@ -0,0 +1,23 @@
+//
+//  TZTestCell.h
+//  TZImagePickerController
+//
+//  Created by 尹彬 on 17/10/7.
+//  Copyright © 2017年 尹彬. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+@interface TZTestCell : UICollectionViewCell
+
+@property (nonatomic, strong) UIImageView *imageView;
+@property (nonatomic, strong) UIImageView *videoImageView;
+@property (nonatomic, strong) UIButton *deleteBtn;
+@property (nonatomic, strong) UILabel *gifLable;
+@property (nonatomic, assign) NSInteger row;
+@property (nonatomic, strong) id asset;
+
+- (UIView *)snapshotView;
+
+@end
+

+ 100 - 0
Examples/Objective-C/Examples/CustomRows/TZImagePicker/TZTestCell.m

@@ -0,0 +1,100 @@
+//
+//  TZTestCell.m
+//  TZImagePickerController
+//
+//  Created by 尹彬 on 17/10/7.
+//  Copyright © 2017年 尹彬. All rights reserved.
+//
+
+#import "TZTestCell.h"
+#import "UIView+Layout.h"
+#import <Photos/Photos.h>
+#import <AssetsLibrary/AssetsLibrary.h>
+#import "TZImagePickerController/TZImagePickerController.h"
+
+@implementation TZTestCell
+
+- (instancetype)initWithFrame:(CGRect)frame {
+    self = [super initWithFrame:frame];
+    if (self) {
+        self.backgroundColor       = [UIColor whiteColor];
+        _imageView                 = [[UIImageView alloc] init];
+        _imageView.backgroundColor = [UIColor colorWithWhite:1.000 alpha:0.500];
+        _imageView.contentMode     = UIViewContentModeScaleAspectFit;
+        [self addSubview:_imageView];
+        self.clipsToBounds = YES;
+        
+        _videoImageView             = [[UIImageView alloc] init];
+        _videoImageView.image       = [UIImage imageNamedFromMyBundle:@"MMVideoPreviewPlay"];
+        _videoImageView.contentMode = UIViewContentModeScaleAspectFill;
+        _videoImageView.hidden      = YES;
+        [self addSubview:_videoImageView];
+        
+        _deleteBtn = [UIButton buttonWithType:UIButtonTypeCustom];
+        [_deleteBtn setImage:[UIImage imageNamed:@"photo_delete"] forState:UIControlStateNormal];
+        _deleteBtn.imageEdgeInsets = UIEdgeInsetsMake(-10, 0, 0, -10);
+        _deleteBtn.alpha           = 0.6;
+        [self addSubview:_deleteBtn];
+        
+        _gifLable                 = [[UILabel alloc] init];
+        _gifLable.text            = @"GIF";
+        _gifLable.textColor       = [UIColor whiteColor];
+        _gifLable.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.8];
+        _gifLable.textAlignment   = NSTextAlignmentCenter;
+        _gifLable.font            = [UIFont systemFontOfSize:10];
+        [self addSubview:_gifLable];
+    }
+    return self;
+}
+
+- (void)layoutSubviews {
+    [super layoutSubviews];
+    _imageView.frame      = self.bounds;
+    _gifLable.frame       = CGRectMake(self.tz_width - 25, self.tz_height - 14, 25, 14);
+    _deleteBtn.frame      = CGRectMake(self.tz_width - 36, 0, 36, 36);
+    CGFloat width         = self.tz_width / 3.0;
+    _videoImageView.frame = CGRectMake(width, width, width, width);
+}
+
+- (void)setAsset:(id)asset {
+    _asset = asset;
+    if ([asset isKindOfClass:[PHAsset class]]) {
+        PHAsset *phAsset       = asset;
+        _videoImageView.hidden = phAsset.mediaType != PHAssetMediaTypeVideo;
+        _gifLable.hidden       = ![[phAsset valueForKey:@"filename"] tz_containsString:@"GIF"];
+    } else if ([asset isKindOfClass:[ALAsset class]]) {
+        ALAsset *alAsset       = asset;
+        _videoImageView.hidden = ![[alAsset valueForProperty:ALAssetPropertyType] isEqualToString:ALAssetTypeVideo];
+        _gifLable.hidden       = YES;
+    }
+}
+
+- (void)setRow:(NSInteger)row {
+    _row           = row;
+    _deleteBtn.tag = row;
+}
+
+- (UIView *)snapshotView {
+    UIView *snapshotView = [[UIView alloc]init];
+    
+    UIView *cellSnapshotView = nil;
+    
+    if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)]) {
+        cellSnapshotView = [self snapshotViewAfterScreenUpdates:NO];
+    } else {
+        CGSize size = CGSizeMake(self.bounds.size.width + 20, self.bounds.size.height + 20);
+        UIGraphicsBeginImageContextWithOptions(size, self.opaque, 0);
+        [self.layer renderInContext:UIGraphicsGetCurrentContext()];
+        UIImage * cellSnapshotImage = UIGraphicsGetImageFromCurrentImageContext();
+        UIGraphicsEndImageContext();
+        cellSnapshotView = [[UIImageView alloc]initWithImage:cellSnapshotImage];
+    }
+    
+    snapshotView.frame     = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height);
+    cellSnapshotView.frame = CGRectMake(0, 0, cellSnapshotView.frame.size.width, cellSnapshotView.frame.size.height);
+    
+    [snapshotView addSubview:cellSnapshotView];
+    return snapshotView;
+}
+
+@end

+ 39 - 0
Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.h

@@ -0,0 +1,39 @@
+//  XLFormWeekDaysCell.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 "XLFormBaseCell.h"
+
+extern NSString * const XLFormRowDescriptorTypeWeekDays;
+
+extern NSString *const kSunday;
+extern NSString *const kMonday;
+extern NSString *const kTuesday;
+extern NSString *const kWednesday;
+extern NSString *const kThursday;
+extern NSString *const kFriday;
+extern NSString *const kSaturday;
+
+@interface XLFormWeekDaysCell : XLFormBaseCell
+
+@end

+ 154 - 0
Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.m

@@ -0,0 +1,154 @@
+//  XLFormWeekDaysCell.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 "XLFormWeekDaysCell.h"
+
+NSString * const XLFormRowDescriptorTypeWeekDays = @"XLFormRowDescriptorTypeWeekDays";
+
+NSString *const kSunday= @"sunday";
+NSString *const kMonday = @"monday";
+NSString *const kTuesday = @"tuesday";
+NSString *const kWednesday = @"wednesday";
+NSString *const kThursday = @"thursday";
+NSString *const kFriday = @"friday";
+NSString *const kSaturday = @"saturday";
+
+@interface XLFormWeekDaysCell()
+@property (weak, nonatomic) IBOutlet UIButton *sundayButton;
+@property (weak, nonatomic) IBOutlet UIButton *mondayButton;
+@property (weak, nonatomic) IBOutlet UIButton *tuesdayButton;
+@property (weak, nonatomic) IBOutlet UIButton *wednesdayButton;
+@property (weak, nonatomic) IBOutlet UIButton *thursdayButton;
+@property (weak, nonatomic) IBOutlet UIButton *fridayButton;
+@property (weak, nonatomic) IBOutlet UIButton *saturdayButton;
+@end
+
+@implementation XLFormWeekDaysCell
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:NSStringFromClass([XLFormWeekDaysCell class]) forKey:XLFormRowDescriptorTypeWeekDays];
+}
+
+#pragma mark - XLFormDescriptorCell
+
+- (void)configure
+{
+    [super configure];
+    
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    [self configureButtons];
+}
+
+-(void)update
+{
+    [super update];
+    [self updateButtons];
+}
+
+#pragma mark - Action
+
+- (IBAction)dayTapped:(id)sender {
+    [self dayTapped:sender day:[self getDayFormButton:sender]];
+}
+
+#pragma mark - Helpers
+
+-(void)configureButtons
+{
+    for (UIView *subview in self.contentView.subviews)
+    {
+        if ([subview isKindOfClass:[UIButton class]])
+        {
+            UIButton * button = (UIButton *)subview;
+            [button setImage:[UIImage imageNamed:@"uncheckedDay"] forState:UIControlStateNormal];
+            [button setImage:[UIImage imageNamed:@"checkedDay"] forState:UIControlStateSelected];
+            button.adjustsImageWhenHighlighted = NO;
+            [self imageTopTitleBottom:button];
+        }
+    }
+}
+
+-(void)updateButtons
+{
+    NSDictionary * value = self.rowDescriptor.value;
+    self.sundayButton.selected = [[value objectForKey:kSunday] boolValue];
+    self.mondayButton.selected = [[value objectForKey:kMonday] boolValue];
+    self.tuesdayButton.selected = [[value objectForKey:kTuesday] boolValue];
+    self.wednesdayButton.selected = [[value objectForKey:kWednesday] boolValue];
+    self.thursdayButton.selected = [[value objectForKey:kThursday] boolValue];
+    self.fridayButton.selected = [[value objectForKey:kFriday] boolValue];
+    self.saturdayButton.selected = [[value objectForKey:kSaturday] boolValue];
+    
+    [self.sundayButton setAlpha:((self.rowDescriptor.isDisabled) ? .6 : 1)];
+    [self.mondayButton setAlpha:self.sundayButton.alpha];
+    [self.tuesdayButton setAlpha:self.sundayButton.alpha];
+    [self.wednesdayButton setAlpha:self.sundayButton.alpha];
+    [self.thursdayButton setAlpha:self.sundayButton.alpha];
+    [self.fridayButton setAlpha:self.sundayButton.alpha];
+    [self.saturdayButton setAlpha:self.sundayButton.alpha];
+}
+
+-(NSString *)getDayFormButton:(id)sender
+{
+    if (sender == self.sundayButton) return kSunday;
+    if (sender == self.mondayButton) return kMonday;
+    if (sender == self.tuesdayButton) return kTuesday;
+    if (sender == self.wednesdayButton) return kWednesday;
+    if (sender == self.thursdayButton) return kThursday;
+    if (sender == self.fridayButton) return kFriday;
+    return kSaturday;
+}
+
+-(void)dayTapped:(UIButton *)button day:(NSString *)day
+{
+    button.selected = !button.selected;
+    NSMutableDictionary * value = [self.rowDescriptor.value mutableCopy];
+    [value setObject:@(button.selected) forKey:day];
+    self.rowDescriptor.value = value;
+}
+
+-(void)imageTopTitleBottom:(UIButton *)button
+{
+    // the space between the image and text
+    CGFloat spacing = 3.0;
+    
+    // lower the text and push it left so it appears centered
+    //  below the image
+    CGSize imageSize = button.imageView.image.size;
+    button.titleEdgeInsets = UIEdgeInsetsMake(0.0, - imageSize.width, - (imageSize.height + spacing), 0.0);
+    
+    // raise the image and push it right so it appears centered
+    //  above the text
+    CGSize titleSize = [button.titleLabel.text sizeWithAttributes:@{NSFontAttributeName: button.titleLabel.font}];
+    button.imageEdgeInsets = UIEdgeInsetsMake(- (titleSize.height + spacing), 0.0, 0.0, - titleSize.width);
+}
+
++(CGFloat)formDescriptorCellHeightForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor
+{
+    return 60;
+}
+
+
+@end

+ 202 - 0
Examples/Objective-C/Examples/CustomRows/Weekdays/XLFormWeekDaysCell.xib

@@ -0,0 +1,202 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="14F27" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
+        <capability name="Constraints to layout margins" minToolsVersion="6.0"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="60" id="piA-L5-eiN" customClass="XLFormWeekDaysCell">
+            <rect key="frame" x="0.0" y="0.0" width="382" height="50"/>
+            <autoresizingMask key="autoresizingMask"/>
+            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" tableViewCell="piA-L5-eiN" id="Yr6-3E-keb">
+                <rect key="frame" x="0.0" y="0.0" width="382" height="49"/>
+                <autoresizingMask key="autoresizingMask"/>
+                <subviews>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZAg-Me-yKR">
+                        <rect key="frame" x="8" y="0.0" width="52" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="S">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <state key="selected">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="K4V-Xd-Bak"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="UjQ-Cw-7wH" userLabel="separator 1">
+                        <rect key="frame" x="60" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="K3N-3h-MZr"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="N3w-qP-kRZ">
+                        <rect key="frame" x="60" y="0.0" width="53" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="M">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="FaQ-oB-Nkl"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kwc-0w-V51" userLabel="separator 2">
+                        <rect key="frame" x="113" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="3mE-sT-ql1"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="cPl-47-rS8">
+                        <rect key="frame" x="113" y="0.0" width="52" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="T">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="4vk-5n-jge"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="EiN-2p-Oig" userLabel="separator 3">
+                        <rect key="frame" x="165" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="JyW-GC-0A7"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="6iC-Cl-RyI">
+                        <rect key="frame" x="165" y="0.0" width="52" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="W">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="oO1-zj-XRv"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bRc-5e-QAH" userLabel="separator 4">
+                        <rect key="frame" x="217" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="W9F-iR-Leh"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="eTo-Ip-reh">
+                        <rect key="frame" x="217" y="0.0" width="52" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="T">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="SkQ-0a-9Fy"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="dHj-rj-mjh" userLabel="separator 5">
+                        <rect key="frame" x="269" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="h5U-x0-9nJ"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Wjb-tu-QEo">
+                        <rect key="frame" x="269" y="0.0" width="53" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="F">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="9A8-9a-SGG"/>
+                        </connections>
+                    </button>
+                    <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="L7g-lu-boa" userLabel="separator 6">
+                        <rect key="frame" x="322" y="10" width="1" height="29"/>
+                        <color key="backgroundColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstAttribute="width" constant="1" id="81t-Xh-wZT"/>
+                        </constraints>
+                    </view>
+                    <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="LNf-b4-GYP">
+                        <rect key="frame" x="322" y="0.0" width="52" height="49"/>
+                        <fontDescription key="fontDescription" type="system" pointSize="16"/>
+                        <state key="normal" title="S">
+                            <color key="titleColor" cocoaTouchSystemColor="darkTextColor"/>
+                            <color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
+                        </state>
+                        <connections>
+                            <action selector="dayTapped:" destination="piA-L5-eiN" eventType="touchUpInside" id="I4k-Ho-KxE"/>
+                        </connections>
+                    </button>
+                </subviews>
+                <constraints>
+                    <constraint firstItem="6iC-Cl-RyI" firstAttribute="width" secondItem="cPl-47-rS8" secondAttribute="width" id="1ZI-HN-9ew"/>
+                    <constraint firstAttribute="bottom" secondItem="EiN-2p-Oig" secondAttribute="bottom" constant="10" id="5eK-Bu-wpU"/>
+                    <constraint firstItem="LNf-b4-GYP" firstAttribute="trailing" secondItem="Yr6-3E-keb" secondAttribute="trailingMargin" id="7Kc-RO-8KK"/>
+                    <constraint firstItem="LNf-b4-GYP" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="7YT-x4-m88"/>
+                    <constraint firstItem="6iC-Cl-RyI" firstAttribute="trailing" secondItem="bRc-5e-QAH" secondAttribute="leading" id="ABd-MQ-9sp"/>
+                    <constraint firstAttribute="bottom" secondItem="UjQ-Cw-7wH" secondAttribute="bottom" constant="10" id="ASC-xR-Yxa"/>
+                    <constraint firstAttribute="bottom" secondItem="dHj-rj-mjh" secondAttribute="bottom" constant="10" id="ASP-um-b8o"/>
+                    <constraint firstItem="6iC-Cl-RyI" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="Aac-10-vTs"/>
+                    <constraint firstItem="eTo-Ip-reh" firstAttribute="leading" secondItem="6iC-Cl-RyI" secondAttribute="trailing" id="BL5-PL-pac"/>
+                    <constraint firstAttribute="bottom" secondItem="ZAg-Me-yKR" secondAttribute="bottom" id="BeZ-ar-qMN"/>
+                    <constraint firstAttribute="bottom" secondItem="kwc-0w-V51" secondAttribute="bottom" constant="10" id="EXu-BP-ftM"/>
+                    <constraint firstAttribute="bottom" secondItem="LNf-b4-GYP" secondAttribute="bottom" id="EYe-ne-rqO"/>
+                    <constraint firstItem="cPl-47-rS8" firstAttribute="leading" secondItem="N3w-qP-kRZ" secondAttribute="trailing" id="Fo8-Tp-bkn"/>
+                    <constraint firstItem="dHj-rj-mjh" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="GYq-pf-vR0"/>
+                    <constraint firstItem="Wjb-tu-QEo" firstAttribute="leading" secondItem="eTo-Ip-reh" secondAttribute="trailing" id="I0s-Ze-pwV"/>
+                    <constraint firstAttribute="bottom" secondItem="bRc-5e-QAH" secondAttribute="bottom" constant="10" id="InL-Hk-twg"/>
+                    <constraint firstItem="UjQ-Cw-7wH" firstAttribute="leading" secondItem="ZAg-Me-yKR" secondAttribute="trailing" id="Jj4-jg-rdr"/>
+                    <constraint firstItem="cPl-47-rS8" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="Kw5-3R-qXs"/>
+                    <constraint firstItem="bRc-5e-QAH" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="MXG-vB-U8F"/>
+                    <constraint firstItem="ZAg-Me-yKR" firstAttribute="width" secondItem="N3w-qP-kRZ" secondAttribute="width" id="Mem-UJ-5Js"/>
+                    <constraint firstItem="L7g-lu-boa" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="OVT-GJ-zq8"/>
+                    <constraint firstItem="N3w-qP-kRZ" firstAttribute="width" secondItem="cPl-47-rS8" secondAttribute="width" id="Pl6-Xd-Krq"/>
+                    <constraint firstItem="Wjb-tu-QEo" firstAttribute="width" secondItem="LNf-b4-GYP" secondAttribute="width" id="Pro-fg-wBA"/>
+                    <constraint firstAttribute="bottom" secondItem="6iC-Cl-RyI" secondAttribute="bottom" id="Q5M-8N-hIh"/>
+                    <constraint firstItem="UjQ-Cw-7wH" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="RGn-ja-FRD"/>
+                    <constraint firstAttribute="bottom" secondItem="N3w-qP-kRZ" secondAttribute="bottom" id="STf-aE-Y2E"/>
+                    <constraint firstAttribute="bottom" secondItem="cPl-47-rS8" secondAttribute="bottom" id="Tmp-md-564"/>
+                    <constraint firstItem="6iC-Cl-RyI" firstAttribute="leading" secondItem="cPl-47-rS8" secondAttribute="trailing" id="VcV-kz-XBb"/>
+                    <constraint firstItem="eTo-Ip-reh" firstAttribute="width" secondItem="6iC-Cl-RyI" secondAttribute="width" id="X0k-jG-o63"/>
+                    <constraint firstItem="EiN-2p-Oig" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="fgT-6k-CaP"/>
+                    <constraint firstItem="LNf-b4-GYP" firstAttribute="leading" secondItem="Wjb-tu-QEo" secondAttribute="trailing" id="gNl-wJ-ujY"/>
+                    <constraint firstItem="ZAg-Me-yKR" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="glN-lT-q1z"/>
+                    <constraint firstItem="eTo-Ip-reh" firstAttribute="width" secondItem="Wjb-tu-QEo" secondAttribute="width" id="hEH-9C-pGZ"/>
+                    <constraint firstItem="eTo-Ip-reh" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="i5C-wG-rRN"/>
+                    <constraint firstItem="eTo-Ip-reh" firstAttribute="trailing" secondItem="dHj-rj-mjh" secondAttribute="leading" id="jsw-H6-2gQ"/>
+                    <constraint firstAttribute="bottom" secondItem="L7g-lu-boa" secondAttribute="bottom" constant="10" id="lv1-xB-0zR"/>
+                    <constraint firstItem="kwc-0w-V51" firstAttribute="leading" secondItem="N3w-qP-kRZ" secondAttribute="trailing" id="oQe-Qf-9ZO"/>
+                    <constraint firstItem="Wjb-tu-QEo" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="pn7-s8-fDj"/>
+                    <constraint firstItem="EiN-2p-Oig" firstAttribute="leading" secondItem="cPl-47-rS8" secondAttribute="trailing" id="qIf-aB-2ZY"/>
+                    <constraint firstItem="kwc-0w-V51" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" constant="10" id="tVL-uj-6Ma"/>
+                    <constraint firstItem="Wjb-tu-QEo" firstAttribute="trailing" secondItem="L7g-lu-boa" secondAttribute="leading" id="u3Q-pF-E3A"/>
+                    <constraint firstAttribute="bottom" secondItem="Wjb-tu-QEo" secondAttribute="bottom" id="uh4-LM-Ieo"/>
+                    <constraint firstItem="ZAg-Me-yKR" firstAttribute="leading" secondItem="Yr6-3E-keb" secondAttribute="leadingMargin" id="w9K-VP-JpE"/>
+                    <constraint firstAttribute="bottom" secondItem="eTo-Ip-reh" secondAttribute="bottom" id="xIu-Vy-Nff"/>
+                    <constraint firstItem="N3w-qP-kRZ" firstAttribute="leading" secondItem="ZAg-Me-yKR" secondAttribute="trailing" id="xsx-BM-yQ5"/>
+                    <constraint firstItem="N3w-qP-kRZ" firstAttribute="top" secondItem="Yr6-3E-keb" secondAttribute="top" id="yEX-Wv-CZQ"/>
+                </constraints>
+            </tableViewCellContentView>
+            <connections>
+                <outlet property="fridayButton" destination="Wjb-tu-QEo" id="AcP-Qg-i9P"/>
+                <outlet property="mondayButton" destination="N3w-qP-kRZ" id="u3A-mt-EKd"/>
+                <outlet property="saturdayButton" destination="LNf-b4-GYP" id="TeM-3b-B1Z"/>
+                <outlet property="sundayButton" destination="ZAg-Me-yKR" id="GUI-ry-Hm1"/>
+                <outlet property="thursdayButton" destination="eTo-Ip-reh" id="Dxi-hi-oBK"/>
+                <outlet property="tuesdayButton" destination="cPl-47-rS8" id="wIn-mO-cUx"/>
+                <outlet property="wednesdayButton" destination="6iC-Cl-RyI" id="GQe-Oy-pcd"/>
+            </connections>
+            <point key="canvasLocation" x="443" y="197"/>
+        </tableViewCell>
+    </objects>
+</document>

+ 35 - 0
Examples/Objective-C/Examples/Dates/DateAndTimeValueTrasformer.h

@@ -0,0 +1,35 @@
+//
+//  DateAndTimeValueTransformer.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+@interface DateValueTrasformer : NSValueTransformer
+@end
+
+@interface DateTimeValueTrasformer : NSValueTransformer
+@end
+
+@interface DateAndTimeValueTrasformer : NSValueTransformer
+@end

+ 89 - 0
Examples/Objective-C/Examples/Dates/DateAndTimeValueTrasformer.m

@@ -0,0 +1,89 @@
+//
+//  DateAndTimeValueTransformer.m
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "DateAndTimeValueTrasformer.h"
+
+
+@implementation DateValueTrasformer
+
++ (Class)transformedValueClass
+{
+    return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+    return NO;
+}
+
+- (id)transformedValue:(id)value
+{
+    if (!value) return nil;
+    if ([value isKindOfClass:[NSDate class]]){
+        NSDate * date = (NSDate *)value;
+        NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
+        [dateFormatter setDateStyle:NSDateFormatterFullStyle];
+        [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
+        return [dateFormatter stringFromDate:date];
+    }
+    return nil;
+}
+
+@end
+
+
+
+@implementation DateTimeValueTrasformer
+
++ (Class)transformedValueClass
+{
+    return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+    return NO;
+}
+
+- (id)transformedValue:(id)value
+{
+    if (!value) return nil;
+    if ([value isKindOfClass:[NSDate class]]){
+        NSDate * date = (NSDate *)value;
+        NSDateFormatter * dateFormatter = [[NSDateFormatter alloc] init];
+        [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
+        [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
+        return [dateFormatter stringFromDate:date];
+    }
+    return nil;
+}
+
+@end
+
+
+
+@implementation DateAndTimeValueTrasformer
+
+@end

+ 31 - 0
Examples/Objective-C/Examples/Dates/DatesFormViewController.h

@@ -0,0 +1,31 @@
+//
+//  DatesFormViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface DatesFormViewController : XLFormViewController
+
+@end

+ 191 - 0
Examples/Objective-C/Examples/Dates/DatesFormViewController.m

@@ -0,0 +1,191 @@
+//
+//  DatesFormViewController.m
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+// 
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+NSString *const kDateInline = @"dateInline";
+NSString *const kTimeInline = @"timeInline";
+NSString *const kDateTimeInline = @"dateTimeInline";
+NSString *const kCountDownTimerInline = @"countDownTimerInline";
+NSString *const kDatePicker = @"datePicker";
+NSString *const kDate = @"date";
+NSString *const kTime = @"time";
+NSString *const kDateTime = @"dateTime";
+NSString *const kCountDownTimer = @"countDownTimer";
+
+#import "DatesFormViewController.h"
+@interface DatesFormViewController() <XLFormDescriptorDelegate>
+@end
+
+@implementation DatesFormViewController
+
+
+- (id)init
+{
+    self = [super init];
+    if (self){
+        XLFormDescriptor * form;
+        XLFormSectionDescriptor * section;
+        
+        XLFormRowDescriptor * row;
+        
+        form = [XLFormDescriptor formDescriptorWithTitle:@"Date & Time"];
+        
+        section = [XLFormSectionDescriptor formSectionWithTitle:@"Inline Dates"];
+        [form addFormSection:section];
+        
+        // Date
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateInline rowType:XLFormRowDescriptorTypeDateInline title:@"Date"];
+        row.value = [NSDate new];
+        [row.cellConfigAtConfigure setObject:[NSLocale localeWithLocaleIdentifier:@"FR_fr" ] forKey:@"locale"];
+        [section addFormRow:row];
+        
+        // Time
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kTimeInline rowType:XLFormRowDescriptorTypeTimeInline title:@"Time"];
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        // DateTime
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateTimeInline rowType:XLFormRowDescriptorTypeDateTimeInline title:@"Date Time"];
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        // CountDownTimer
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kCountDownTimerInline rowType:XLFormRowDescriptorTypeCountDownTimerInline title:@"Countdown Timer"];
+        NSDateComponents * dateComp = [NSDateComponents new];
+        dateComp.hour = 0;
+        dateComp.minute = 7;
+        dateComp.timeZone = [NSTimeZone systemTimeZone];
+        NSCalendar * calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
+        row.value = [calendar dateFromComponents:dateComp];
+        [section addFormRow:row];
+        
+        
+        section = [XLFormSectionDescriptor formSectionWithTitle:@"Dates"];
+        [form addFormSection:section];
+        
+        // Date
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDate rowType:XLFormRowDescriptorTypeDate title:@"Date"];
+        row.value = [NSDate new];
+        [row.cellConfigAtConfigure setObject:[NSDate new] forKey:@"minimumDate"];
+        [row.cellConfigAtConfigure setObject:[NSDate dateWithTimeIntervalSinceNow:(60*60*24*3)] forKey:@"maximumDate"];
+        [section addFormRow:row];
+        
+        // Time
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kTime rowType:XLFormRowDescriptorTypeTime title:@"Time"];
+        [row.cellConfigAtConfigure setObject:@(10) forKey:@"minuteInterval"];
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        // DateTime
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDateTime rowType:XLFormRowDescriptorTypeDateTime title:@"Date Time"];
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        // CountDownTimer
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kCountDownTimerInline rowType:XLFormRowDescriptorTypeCountDownTimer title:@"Countdown Timer"];
+        row.value = [calendar dateFromComponents:dateComp];
+        [section addFormRow:row];
+        
+        section = [XLFormSectionDescriptor formSectionWithTitle:@"Disabled Dates"];
+        //section.footerTitle = @"DatesFormViewController.h";
+        [form addFormSection:section];
+        
+        // Date
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDate rowType:XLFormRowDescriptorTypeDate title:@"Date"];
+        row.disabled = @YES;
+        row.required = YES;
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        // DatePicker
+        section = [XLFormSectionDescriptor formSectionWithTitle:@"DatePicker"];
+        [form addFormSection:section];
+        
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kDatePicker rowType:XLFormRowDescriptorTypeDatePicker];
+        [row.cellConfigAtConfigure setObject:@(UIDatePickerModeDate) forKey:@"datePicker.datePickerMode"];
+        row.value = [NSDate new];
+        [section addFormRow:row];
+        
+        
+        self.form = form;
+    }
+    return self;
+}
+
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithTitle:@"Disable" style:UIBarButtonItemStylePlain
+                                                                  target:self
+                                                                  action:@selector(disableEnable:)];
+    barButton.possibleTitles = [NSSet setWithObjects:@"Disable", @"Enable", nil];
+    self.navigationItem.rightBarButtonItem = barButton;
+}
+
+-(void)disableEnable:(UIBarButtonItem *)button
+{
+    self.form.disabled = !self.form.disabled;
+    [button setTitle:(self.form.disabled ? @"Enable" : @"Disable")];
+    [self.tableView endEditing:YES];
+    [self.tableView reloadData];
+}
+
+-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)formRow oldValue:(id)oldValue newValue:(id)newValue
+{
+    // super implementation must be called
+    [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
+    }
+}
+
+
+@end

BIN
Examples/Objective-C/Examples/Dates/XLForm-Dates.gif


+ 30 - 0
Examples/Objective-C/Examples/ExamplesFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  ExamplesFormViewController.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 "XLFormViewController.h"
+
+@interface ExamplesFormViewController : XLFormViewController
+
+@end

+ 200 - 0
Examples/Objective-C/Examples/ExamplesFormViewController.m

@@ -0,0 +1,200 @@
+//
+//  ExamplesFormViewController.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 "InputsFormViewController.h"
+#import "SelectorsFormViewController.h"
+#import "OthersFormViewController.h"
+#import "DatesFormViewController.h"
+#import "MultiValuedFormViewController.h"
+#import "ExamplesFormViewController.h"
+#import "NativeEventFormViewController.h"
+#import "UICustomizationFormViewController.h"
+#import "CustomRowsViewController.h"
+#import "AccessoryViewFormViewController.h"
+#import "PredicateFormViewController.h"
+#import "FormattersViewController.h"
+
+NSString * const kTextFieldAndTextView = @"TextFieldAndTextView";
+NSString * const kSelectors = @"Selectors";
+NSString * const kOthes = @"Others";
+NSString * const kDates = @"Dates";
+NSString * const kPredicates = @"BasicPredicates";
+NSString * const kBlogExample = @"BlogPredicates";
+NSString * const kMultivalued = @"Multivalued";
+NSString * const kMultivaluedOnlyReorder = @"MultivaluedOnlyReorder";
+NSString * const kMultivaluedOnlyInsert = @"MultivaluedOnlyInsert";
+NSString * const kMultivaluedOnlyDelete = @"MultivaluedOnlyDelete";
+NSString * const kValidations= @"Validations";
+NSString * const kFormatters = @"Formatters";
+
+@interface ExamplesFormViewController ()
+
+@end
+
+@implementation ExamplesFormViewController
+
+
+-(instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self){
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+-(id)initWithCoder:(NSCoder *)aDecoder
+{
+    self = [super initWithCoder:aDecoder];
+    if (self){
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+#pragma mark - Helper
+
+-(void)initializeForm
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    form = [XLFormDescriptor formDescriptor];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Real examples"];
+    [form addFormSection:section];
+    
+    // NativeEventFormViewController
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"realExamples" rowType:XLFormRowDescriptorTypeButton title:@"iOS Calendar Event Form"];
+    row.action.formSegueIdentifier = @"NativeEventNavigationViewControllerSegue";
+    [section addFormRow:row];
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"This form is actually an example"];
+    section.footerTitle = @"ExamplesFormViewController.h, Select an option to view another example";
+    [form addFormSection:section];
+    
+    
+    // TextFieldAndTextView
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kTextFieldAndTextView rowType:XLFormRowDescriptorTypeButton title:@"Text Fields"];
+    row.action.viewControllerClass = [InputsFormViewController class];
+    [section addFormRow:row];
+    
+    // Selectors
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectors rowType:XLFormRowDescriptorTypeButton title:@"Selectors"];
+    row.action.formSegueIdentifier = @"SelectorsFormViewControllerSegue";
+    [section addFormRow:row];
+    
+    // Dates
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kDates rowType:XLFormRowDescriptorTypeButton title:@"Date & Time"];
+    row.action.viewControllerClass = [DatesFormViewController class];
+    [section addFormRow:row];
+    
+    // NSFormatters
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kFormatters rowType:XLFormRowDescriptorTypeButton title:@"NSFormatter Support"];
+    row.action.viewControllerClass = [FormattersViewController class];
+    [section addFormRow:row];
+    
+    // Others
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kOthes rowType:XLFormRowDescriptorTypeButton title:@"Other Rows"];
+    row.action.formSegueIdentifier = @"OthersFormViewControllerSegue";
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Multivalued example"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivalued rowType:XLFormRowDescriptorTypeButton title:@"Multivalued Sections"];
+    row.action.viewControllerClass = [MultivaluedFormViewController class];
+    [section addFormRow:row];
+    
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivaluedOnlyReorder rowType:XLFormRowDescriptorTypeButton title:@"Multivalued Only Reorder"];
+    row.action.viewControllerClass = [MultivaluedOnlyReorderViewController class];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivaluedOnlyInsert rowType:XLFormRowDescriptorTypeButton title:@"Multivalued Only Insert"];
+    row.action.viewControllerClass = [MultivaluedOnlyInserViewController class];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivaluedOnlyDelete rowType:XLFormRowDescriptorTypeButton title:@"Multivalued Only Delete"];
+    row.action.viewControllerClass = [MultivaluedOnlyDeleteViewController class];
+    [section addFormRow:row];
+    
+
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"UI Customization"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivalued rowType:XLFormRowDescriptorTypeButton title:@"UI Customization"];
+    row.action.viewControllerClass = [UICustomizationFormViewController class];
+    [section addFormRow:row];
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Custom Rows"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivalued rowType:XLFormRowDescriptorTypeButton title:@"Custom Rows"];
+    row.action.viewControllerClass = [CustomRowsViewController class];
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Accessory View"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultivalued rowType:XLFormRowDescriptorTypeButton title:@"Accessory Views"];
+    row.action.viewControllerClass = [AccessoryViewFormViewController class];
+    [section addFormRow:row];
+
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Examples"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kValidations rowType:XLFormRowDescriptorTypeButton title:@"Validation Examples"];
+    row.action.formSegueIdentifier = @"ValidationExamplesFormViewControllerSegue";
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Using Predicates"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Very basic predicates"];
+    row.action.formSegueIdentifier = @"BasicPredicateViewControllerSegue";
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Blog Example Hide predicates"];
+    row.action.formSegueIdentifier = @"BlogExampleViewSegue";
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredicates rowType:XLFormRowDescriptorTypeButton title:@"Another example"];
+    row.action.formSegueIdentifier = @"PredicateFormViewControllerSegue";
+    [section addFormRow:row];
+    
+    self.form = form;
+
+}
+
+
+
+@end

+ 13 - 0
Examples/Objective-C/Examples/Formatters/FormattersViewController.h

@@ -0,0 +1,13 @@
+//
+//  FormattersViewController.h
+//  XLForm
+//
+//  Created by Freddy Henin on 12/29/14.
+//  Copyright (c) 2014 Xmartlabs. All rights reserved.
+//
+
+#import "XLFormViewController.h"
+
+@interface FormattersViewController : XLFormViewController
+
+@end

+ 120 - 0
Examples/Objective-C/Examples/Formatters/FormattersViewController.m

@@ -0,0 +1,120 @@
+//
+//  FormattersViewController.m
+//  XLForm
+//
+//  Created by Freddy Henin on 12/29/14.
+//  Copyright (c) 2014 Xmartlabs. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+
+#import "XLForm.h"
+
+#import "FormattersViewController.h"
+
+#import <SHSPhoneComponent/SHSPhoneNumberFormatter+UserConfig.h>
+
+
+// Simple little class to demonstraite currency formatting.   Unfortunally we have to subclass
+// NSNumberFormatter to work aroundn some long known rounding bugs with NSNumberFormatter
+//     http://stackoverflow.com/questions/12580162/nsstring-to-nsdate-conversion-issue
+@interface CurrencyFormatter : NSNumberFormatter
+
+@property (readonly) NSDecimalNumberHandler *roundingBehavior;
+
+@end
+
+@implementation CurrencyFormatter
+
+- (id) init
+{
+    self = [super init];
+    if (self) {
+        [self setNumberStyle: NSNumberFormatterCurrencyStyle];
+        [self setGeneratesDecimalNumbers:YES];
+        
+        NSUInteger currencyScale = [self maximumFractionDigits];
+        
+        _roundingBehavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:currencyScale raiseOnExactness:FALSE raiseOnOverflow:TRUE raiseOnUnderflow:TRUE raiseOnDivideByZero:TRUE];
+        
+    }
+    
+    return self;
+}
+
+//- (BOOL)getObjectValue:(id *)anObject forString:(NSString *)string errorDescription:(NSString **)error
+//{
+//    NSDecimalNumber *number;
+//    BOOL success = [super getObjectValue:&number forString:string errorDescription:error];
+//    
+//    if (success) {
+//        *anObject = [number decimalNumberByRoundingAccordingToBehavior:_roundingBehavior];
+//    }
+//    else {
+//        *anObject = nil;
+//    }
+//    
+//    return success;
+//}
+
+@end
+
+@interface FormattersViewController ()
+@end
+
+@implementation FormattersViewController
+
+-(id)init
+{
+    XLFormDescriptor * formDescriptor = [XLFormDescriptor formDescriptorWithTitle:@"Text Fields"];
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    formDescriptor.assignFirstResponderOnShow = NO;
+    
+    section = [XLFormSectionDescriptor formSection];
+    section.title = @"NSFormatter Support";
+    section.footerTitle = @"Rows can be configured to use the formatter as you type or to toggle on and off during for display/editing.  You will most likely need custom NSFormatter objects to do on the fly formatting since NSNumberFormatter is pretty limited in this regard.";
+    [formDescriptor addFormSection:section];
+    
+    // Phone
+    SHSPhoneNumberFormatter *formatter = [[SHSPhoneNumberFormatter alloc] init];
+    [formatter setDefaultOutputPattern:@"(###) ###-####" imagePath:nil];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"phone" rowType:XLFormRowDescriptorTypePhone title:@"US Phone"];
+    row.valueFormatter = formatter;
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    
+    row.useValueFormatterDuringInput = YES;
+    [section addFormRow:row];
+    
+    // Currency
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"currency" rowType:XLFormRowDescriptorTypeDecimal title:@"USD"];
+    CurrencyFormatter *numberFormatter = [[CurrencyFormatter alloc] init];
+    row.valueFormatter = numberFormatter;
+    row.value = [NSDecimalNumber numberWithDouble:9.95];
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    [section addFormRow:row];
+    
+    // Accounting
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"percent" rowType:XLFormRowDescriptorTypeNumber title:@"Test Score"];
+    NSNumberFormatter *acctFormatter = [[NSNumberFormatter alloc] init];
+    [acctFormatter setNumberStyle:NSNumberFormatterPercentStyle];
+    row.valueFormatter = acctFormatter;
+    row.value = @(0.75);
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"megabytes" rowType:XLFormRowDescriptorTypeInfo title:@"Megabytes"];
+    row.valueFormatter = [NSByteCountFormatter new];
+    row.value = @(1024);
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSection];
+    [formDescriptor addFormSection:section];
+    
+    return [super initWithForm:formDescriptor];
+    
+}
+
+@end

+ 30 - 0
Examples/Objective-C/Examples/Inputs/InputsFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  InputsFormViewController.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 "XLFormViewController.h"
+
+@interface InputsFormViewController : XLFormViewController
+
+@end

+ 167 - 0
Examples/Objective-C/Examples/Inputs/InputsFormViewController.m

@@ -0,0 +1,167 @@
+//
+//  InputsFormViewController.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 "XLForm.h"
+#import "InputsFormViewController.h"
+
+
+NSString *const kName = @"name";
+NSString *const kEmail = @"email";
+NSString *const kTwitter = @"twitter";
+NSString *const kZipCode = @"zipCode";
+NSString *const kNumber = @"number";
+NSString *const kInteger = @"integer";
+NSString *const kDecimal = @"decimal";
+NSString *const kPassword = @"password";
+NSString *const kPhone = @"phone";
+NSString *const kUrl = @"url";
+NSString *const kTextView = @"textView";
+NSString *const kNotes = @"notes";
+
+
+@implementation InputsFormViewController
+
+-(id)init
+{
+    XLFormDescriptor * formDescriptor = [XLFormDescriptor formDescriptorWithTitle:@"Text Fields"];
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    formDescriptor.assignFirstResponderOnShow = YES;
+    
+    // Basic Information - Section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"TextField Types"];
+    section.footerTitle = @"This is a long text that will appear on section footer";
+    [formDescriptor addFormSection:section];
+    
+    // Name
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kName rowType:XLFormRowDescriptorTypeText title:@"Name"];
+    row.required = YES;
+    [section addFormRow:row];
+    
+    // Email
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kEmail rowType:XLFormRowDescriptorTypeEmail title:@"Email"];
+    // validate the email
+    [row addValidator:[XLFormValidator emailValidator]];
+    [section addFormRow:row];
+    
+    // Twitter
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kTwitter rowType:XLFormRowDescriptorTypeTwitter title:@"Twitter"];
+    row.disabled = @YES;
+    row.value = @"@no_editable";
+    [section addFormRow:row];
+    
+    // Zip Code
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kZipCode rowType:XLFormRowDescriptorTypeZipCode title:@"Zip Code"];
+    [section addFormRow:row];
+
+    // Number
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kNumber rowType:XLFormRowDescriptorTypeNumber title:@"Number"];
+    [section addFormRow:row];
+    
+    // Integer
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kInteger rowType:XLFormRowDescriptorTypeInteger title:@"Integer"];
+    [section addFormRow:row];
+	
+    // Decimal
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kDecimal rowType:XLFormRowDescriptorTypeDecimal title:@"Decimal"];
+    [section addFormRow:row];
+    
+    // Password
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPassword rowType:XLFormRowDescriptorTypePassword title:@"Password"];
+    [section addFormRow:row];
+    
+    // Phone
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPhone rowType:XLFormRowDescriptorTypePhone title:@"Phone"];
+    [section addFormRow:row];
+    
+    // Url
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kUrl rowType:XLFormRowDescriptorTypeURL title:@"Url"];
+    [section addFormRow:row];
+    
+    
+    section = [XLFormSectionDescriptor formSection];
+    [formDescriptor addFormSection:section];
+    
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kTextView rowType:XLFormRowDescriptorTypeTextView];
+    [row.cellConfigAtConfigure setObject:@"TEXT VIEW EXAMPLE" forKey:@"textView.placeholder"];
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"TextView With Label Example"];
+    [formDescriptor addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kNotes rowType:XLFormRowDescriptorTypeTextView title:@"Notes"];
+    [section addFormRow:row];
+    
+    return [super initWithForm:formDescriptor];
+    
+}
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(savePressed:)];
+}
+
+
+-(void)savePressed:(UIBarButtonItem * __unused)button
+{
+    NSArray * validationErrors = [self formValidationErrors];
+    if (validationErrors.count > 0){
+        [self showFormValidationError:[validationErrors firstObject]];
+        return;
+    }
+    [self.tableView endEditing:YES];
+    
+#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

BIN
Examples/Objective-C/Examples/Inputs/XLForm-Inputs.gif


+ 45 - 0
Examples/Objective-C/Examples/MultiValuedSections/MultivaluedFormViewController.h

@@ -0,0 +1,45 @@
+//
+//  MultiValuedFormViewController.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 "XLFormViewController.h"
+
+@interface MultivaluedFormViewController : XLFormViewController
+
+@end
+
+
+@interface MultivaluedOnlyReorderViewController : XLFormViewController
+
+@end
+
+
+@interface MultivaluedOnlyInserViewController : XLFormViewController
+
+@end
+
+
+@interface MultivaluedOnlyDeleteViewController : XLFormViewController
+
+@end

+ 336 - 0
Examples/Objective-C/Examples/MultiValuedSections/MultivaluedFormViewController.m

@@ -0,0 +1,336 @@
+//
+//  MultiValuedFormViewController.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 "XLForm.h"
+#import "SelectorsFormViewController.h"
+#import "MultiValuedFormViewController.h"
+
+
+@implementation MultivaluedFormViewController
+
+- (id)init
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Multivalued Examples"];
+    
+    // Multivalued section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Multivalued TextField"
+                                             sectionOptions:XLFormSectionOptionCanReorder | XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete
+                                          sectionInsertMode:XLFormSectionInsertModeButton];
+    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 formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeName];
+    [[row cellConfig] setObject:@"Tag Name" forKey:@"textField.placeholder"];
+    section.multivaluedRowTemplate = row;
+    [form addFormSection:section];
+    
+    
+    // Another Multivalued section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Multivalued ActionSheet Selector example"
+                                             sectionOptions:XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete];
+    section.footerTitle = @"XLFormSectionInsertModeLastRow sectionType adds a '+' icon inside last table view cell allowing us to add a new row.";
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorActionSheet title:@"Tap to select.."];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5"];
+    [section addFormRow:row];
+    
+    
+    // Another one
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Multivalued Push Selector example"
+                                             sectionOptions:XLFormSectionOptionCanInsert | XLFormSectionOptionCanDelete | XLFormSectionOptionCanReorder
+                                          sectionInsertMode:XLFormSectionInsertModeButton];
+    section.footerTitle = @"MultivaluedFormViewController.h";
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorPush title:@"Tap to select ;).."];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3"];
+    section.multivaluedRowTemplate = [row copy];
+    [section addFormRow:row];
+    return [super initWithForm:form];
+}
+
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemEdit target:self action:@selector(addDidTouch:)];
+}
+
+#pragma mark - Actions
+
+-(void)addDidTouch:(UIBarButtonItem * __unused)sender
+{
+#if __IPHONE_OS_VERSION_MAX_ALLOWED < 80000
+    UIActionSheet * actionSheet = [[UIActionSheet alloc] initWithTitle:nil
+                                                              delegate:self
+                                                     cancelButtonTitle:NSLocalizedString(@"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:NSLocalizedString(@"Cancel", nil)
+                                                            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:NSLocalizedString(@"Cancel", nil)
+                                                    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
+{
+    if ([actionSheet destructiveButtonIndex] == buttonIndex){
+        if (self.form.formSections.count > 0){
+            // remove last section
+            [self.form removeFormSectionAtIndex:(self.form.formSections.count - 1)];
+        }
+    }
+    else if ([[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:@"Add a section at the end"]){
+        // 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_%@", @(self.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];
+        [self.form addFormSection:newSection];
+    }
+    else if (![[actionSheet buttonTitleAtIndex:buttonIndex] isEqualToString:NSLocalizedString(@"Cancel")]){
+        self.form.disabled = !self.form.disabled;
+        [self.tableView endEditing:YES];
+        [self.tableView reloadData];
+    }
+}
+
+#endif
+
+@end
+
+
+@implementation MultivaluedOnlyReorderViewController
+
+- (id)init
+{
+    NSTimeInterval secondsPerDay = 24 * 60 * 60;
+    NSArray * list = @[@"Today", @"Yesterday", @"Before Yesterday"];
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Only Reorder Examples"];
+    
+    
+    // Multivalued Section with inline rows - section set up to support only reordering
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Reordering Inline Rows"
+                                             sectionOptions:XLFormSectionOptionCanReorder];
+    section.footerTitle = @"XLFormRowDescriptorTypeDateInline row type";
+    [form addFormSection:section];
+    
+    [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeDateInline];
+        row.value = [NSDate dateWithTimeIntervalSinceNow:(-secondsPerDay * idx)];
+        row.title = obj;
+        [section addFormRow:row];
+    }];
+    
+    
+    // Multivalued Section with common rows - section set up to support only reordering
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Reordering Rows"
+                                             sectionOptions:XLFormSectionOptionCanReorder];
+    section.footerTitle = @"XLFormRowDescriptorTypeInfo row type";
+    [form addFormSection:section];
+    
+    
+    [list enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeInfo];
+        row.value = [NSDateFormatter localizedStringFromDate:[NSDate dateWithTimeIntervalSinceNow:(-secondsPerDay * idx)] dateStyle:NSDateFormatterMediumStyle timeStyle:NSDateFormatterNoStyle];
+        row.title = obj;
+        [section addFormRow:row];
+    }];
+    
+    return [super initWithForm:form];
+}
+
+@end
+
+
+@implementation MultivaluedOnlyInserViewController
+
+- (id)init
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    NSArray * nameList = @[@"family", @"male", @"female", @"client"];
+    
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Multivalued Only Insert"];
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"XLFormSectionInsertModeButton"
+                                             sectionOptions:XLFormSectionOptionCanInsert
+                                          sectionInsertMode:XLFormSectionInsertModeButton];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeText];
+    [[row cellConfig] setObject:@"Add a new tag" forKey:@"textField.placeholder"];
+    section.multivaluedRowTemplate = row;
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"XLFormSectionInsertModeButton With Inline Cells"
+                                             sectionOptions:XLFormSectionOptionCanInsert
+                                          sectionInsertMode:XLFormSectionInsertModeButton];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeDateInline];
+    row.value = [NSDate new];
+    row.title = @"Date";
+    section.multivaluedRowTemplate = row;
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"XLFormSectionInsertModeLastRow"
+                                             sectionOptions:XLFormSectionOptionCanInsert
+                                          sectionInsertMode:XLFormSectionInsertModeLastRow];
+    [form addFormSection:section];
+    for (NSString * tag in nameList) {
+        // add a row to the section, the row will be used to crete new rows.
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeText];
+        [[row cellConfig] setObject:@"Add a new tag" forKey:@"textField.placeholder"];
+        row.value = tag;
+        [section addFormRow:row];
+    }
+    
+    return [super initWithForm:form];
+}
+
+@end
+
+
+@implementation MultivaluedOnlyDeleteViewController
+
+- (id)init
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    NSArray * nameList = @[@"family", @"male", @"female", @"client"];
+    
+    
+    form = [XLFormDescriptor formDescriptor];
+    
+    // MultivaluedSection section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@""
+                                             sectionOptions:XLFormSectionOptionCanDelete];
+    section.footerTitle = @"you can swipe to delete when table.editing = NO (Not Editing)";
+    [form addFormSection:section];
+    
+    for (NSString * tag in nameList) {
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeText];
+        [[row cellConfig] setObject:@"Add a new tag" forKey:@"textField.placeholder"];
+        row.value = [tag copy];
+        [section addFormRow:row];
+    }
+    
+    // Multivalued Section with inline row.
+    section = [XLFormSectionDescriptor formSectionWithTitle:@""
+                                             sectionOptions:XLFormSectionOptionCanDelete];
+    section.footerTitle = @"you can swipe to delete when table.editing = NO (Not Editing)";
+    [form addFormSection:section];
+    for (NSUInteger i = 0; i < 4; i++) {
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:XLFormRowDescriptorTypeSelectorPickerViewInline];
+        row.title = @"Tap to select";
+        row.value = @"client";
+        row.selectorOptions = nameList;
+        [section addFormRow:row];
+    }
+    
+    return [super initWithForm:form];
+}
+
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Editing" style:UIBarButtonItemStylePlain target:self action:@selector(toggleEditing:)];
+}
+
+
+-(void)toggleEditing:(UIBarButtonItem *)barButtonItem
+{
+    [self.tableView setEditing:!self.tableView.editing animated:YES];
+    [barButtonItem setTitle:(self.tableView.editing ? @"Editing" : @"Not Editing")];
+}
+
+@end
+

BIN
Examples/Objective-C/Examples/MultiValuedSections/XLForm-MultiValuedSections.gif


+ 30 - 0
Examples/Objective-C/Examples/Others/CustomCells/XLFormCustomCell.h

@@ -0,0 +1,30 @@
+//
+//  XLFormCustomCell.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 "XLFormBaseCell.h"
+
+@interface XLFormCustomCell : XLFormBaseCell
+
+@end

+ 60 - 0
Examples/Objective-C/Examples/Others/CustomCells/XLFormCustomCell.m

@@ -0,0 +1,60 @@
+//
+//  XLFormCustomCell.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 "XLFormCustomCell.h"
+
+@implementation XLFormCustomCell
+
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
+    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
+    if (self) {
+        // Initialization code        
+    }
+    return self;
+}
+
+- (void)configure
+{
+    [super configure];
+    //override
+}
+
+- (void)update
+{
+    [super update];
+    // override
+    self.textLabel.text = @"Am a custom cell, select me!";
+}
+
+-(void)formDescriptorCellDidSelectedWithFormController:(XLFormViewController *)controller
+{
+    // custom code here
+    // i.e new behaviour when cell has been selected
+    self.textLabel.text = [self.textLabel.text isEqualToString:@"I can do any custom behaviour..."] ? @"Am a custom cell, select me!" : @"I can do any custom behaviour...";
+    self.rowDescriptor.value = self.textLabel.text;
+    [self.formViewController.tableView selectRowAtIndexPath:nil animated:YES scrollPosition:UITableViewScrollPositionNone];
+}
+
+@end

+ 36 - 0
Examples/Objective-C/Examples/Others/CustomCells/XLFormImageSelectorCell.h

@@ -0,0 +1,36 @@
+//
+//  XLFormImageSelectorCell.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 "XLFormBaseCell.h"
+
+NSString *const kFormImageSelectorCellDefaultImage;
+NSString *const kFormImageSelectorCellImageRequest;
+
+@interface XLFormImageSelectorCell : XLFormBaseCell
+
+@property (nonatomic, readonly) UIImageView * imageView;
+@property (nonatomic, readonly) UILabel * textLabel;
+
+@end

+ 296 - 0
Examples/Objective-C/Examples/Others/CustomCells/XLFormImageSelectorCell.m

@@ -0,0 +1,296 @@
+//
+//  XLFormImageSelectorCell.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 <MobileCoreServices/MobileCoreServices.h>
+#import "UIView+XLFormAdditions.h"
+#import <AFNetworking/UIImageView+AFNetworking.h>
+#import "XLFormImageSelectorCell.h"
+
+
+NSString *const kFormImageSelectorCellDefaultImage = @"defaultImage";
+NSString *const kFormImageSelectorCellImageRequest = @"imageRequest";
+
+@interface XLFormImageSelectorCell() <UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>
+
+@property (nonatomic) UIImage * defaultImage;
+@property (nonatomic) NSURLRequest * imageRequest;
+
+@end
+
+@implementation XLFormImageSelectorCell{
+    CGFloat _imageHeight;
+    CGFloat _imageWidth;
+}
+@synthesize imageView = _imageView;
+@synthesize textLabel = _textLabel;
+
+
+#pragma mark - XLFormDescriptorCell
+
+
+- (void)configure
+{
+    [super configure];
+    _imageHeight = 100.0f;
+    _imageWidth = 100.0f;
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    self.backgroundColor = [UIColor clearColor];
+    self.separatorInset = UIEdgeInsetsZero;
+    [self.contentView addSubview:self.imageView];
+    [self.contentView addSubview:self.textLabel];
+    [self addLayoutConstraints];
+    [self.textLabel addObserver:self forKeyPath:@"text" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:0];
+
+}
+
+- (void)update
+{
+    self.textLabel.text = self.rowDescriptor.title;
+    self.imageView.image = self.rowDescriptor.value ?: self.defaultImage;
+    if (self.imageRequest && !self.rowDescriptor.value){
+        __weak __typeof(self) weakSelf = self;
+        [self.imageView setImageWithURLRequest:self.imageRequest
+                                   placeholderImage:self.defaultImage
+                                            success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
+                                                if (!weakSelf.rowDescriptor.value && image){
+                                                    [weakSelf.imageView setImage:image];
+                                                }
+                                            }
+                                            failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
+                                                NSLog(@"Failed to download image");
+                                            }];
+    }
+}
+
+
++(CGFloat)formDescriptorCellHeightForRowDescriptor:(XLFormRowDescriptor *)rowDescriptor
+{
+    return 120.0f;
+}
+
+-(void)formDescriptorCellDidSelectedWithFormController:(XLFormViewController *)controller
+{
+#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:NSLocalizedString(@"Cancel", nil)
+                                                            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
+
+-(void)addLayoutConstraints
+{
+    NSDictionary *uiComponents = @{ @"image" : self.imageView,
+                                    @"text"  : self.textLabel};
+    
+    NSDictionary *metrics = @{@"margin":@5.0};
+    
+    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[text]" options:0 metrics:metrics views:uiComponents]];
+    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[text]" options:0 metrics:metrics views:uiComponents]];
+    
+    
+    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView
+                                                                attribute:NSLayoutAttributeTop
+                                                                relatedBy:NSLayoutRelationEqual
+                                                                   toItem:self.contentView
+                                                                attribute:NSLayoutAttributeTop
+                                                               multiplier:1.0f
+                                                                 constant:10.0f]];
+
+    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                 relatedBy:NSLayoutRelationEqual
+                                                                    toItem:self.contentView
+                                                                 attribute:NSLayoutAttributeBottom
+                                                                multiplier:1.0f
+                                                                  constant:-10.0f]];
+    
+    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:[image(width)]" options:0 metrics:@{ @"width" : @(_imageWidth) } views:uiComponents]];
+    [self.contentView addConstraint:[NSLayoutConstraint constraintWithItem:self.imageView
+                                                                          attribute:NSLayoutAttributeCenterX
+                                                                          relatedBy:NSLayoutRelationEqual
+                                                                             toItem:self.contentView
+                                                                          attribute:NSLayoutAttributeCenterX
+                                                                         multiplier:1.0f
+                                                                           constant:0.0f]];
+}
+
+
+-(void)setImageValue:(UIImage *)image
+{
+    self.rowDescriptor.value = image;
+    self.imageView.image = image;
+}
+
+-(void)updateConstraints
+{
+    
+    [super updateConstraints];
+}
+
+#pragma mark - KVO
+
+-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
+{
+    if (object == self.textLabel && [keyPath isEqualToString:@"text"]){
+        if ([[change objectForKey:NSKeyValueChangeKindKey] isEqualToNumber:@(NSKeyValueChangeSetting)]){
+            [self.contentView needsUpdateConstraints];
+        }
+    }
+}
+
+-(void)dealloc
+{
+    [self.textLabel removeObserver:self forKeyPath:@"text"];
+}
+
+
+
+
+#if __IPHONE_OS_VERSION_MIN_REQUIRED < 80000
+
+#pragma mark - UIActionSheetDelegate
+
+- (void)actionSheet:(UIActionSheet * __unused)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
+{
+    UIImagePickerController * imagePickerController = [[UIImagePickerController alloc] init];
+    imagePickerController.delegate = self;
+    imagePickerController.allowsEditing = YES;
+    if (buttonIndex == 0){
+        imagePickerController.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
+        imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
+        [self.formViewController presentViewController:imagePickerController animated:YES completion:nil];
+    }
+    else if (buttonIndex == 1){
+        imagePickerController.sourceType = UIImagePickerControllerSourceTypeCamera;
+        imagePickerController.mediaTypes = @[(NSString *)kUTTypeImage];
+        [self.formViewController presentViewController:imagePickerController animated:YES completion:nil];
+    }
+}
+
+#endif
+
+#pragma mark - UIImagePickerControllerDelegate
+
+- (void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
+{
+    NSString *mediaType = [info objectForKey:UIImagePickerControllerMediaType];
+    UIImage *originalImage, *editedImage, *imageToUse;
+    if (CFStringCompare ((CFStringRef) mediaType, kUTTypeImage, 0) == kCFCompareEqualTo) {
+        // ensure the user has taken a picture
+        editedImage = (UIImage *) [info objectForKey:UIImagePickerControllerEditedImage];
+        originalImage = (UIImage *) [info objectForKey:UIImagePickerControllerOriginalImage];
+        if (editedImage) {
+            imageToUse = editedImage;
+        }
+        else {
+            imageToUse = originalImage;
+        }
+        [self setImageValue:imageToUse];
+    }
+    
+    [self.formViewController dismissViewControllerAnimated:YES completion:nil];
+}
+
+#pragma mark - Properties
+
+-(UIImageView *)imageView
+{
+    if (_imageView) return _imageView;
+    _imageView = [UIImageView autolayoutView];
+    _imageView.layer.masksToBounds = YES;
+    _imageView.contentMode = UIViewContentModeScaleAspectFit;
+    _imageView.layer.cornerRadius = _imageHeight / 2.0;
+    return _imageView;
+}
+
+-(UILabel *)textLabel
+{
+    if (_textLabel) return _textLabel;
+    _textLabel = [UILabel autolayoutView];
+    return _textLabel;
+}
+
+
+-(void)setDefaultImage:(UIImage *)defaultImage
+{
+    _defaultImage = defaultImage;
+}
+
+
+-(void)setImageRequest:(NSURLRequest *)imageRequest
+{
+    _imageRequest = imageRequest;
+}
+
+
+@end

+ 31 - 0
Examples/Objective-C/Examples/Others/OthersFormViewController.h

@@ -0,0 +1,31 @@
+//
+//  OthersFormViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface OthersFormViewController : XLFormViewController
+
+@end

+ 249 - 0
Examples/Objective-C/Examples/Others/OthersFormViewController.m

@@ -0,0 +1,249 @@
+//
+//  OthersFormViewController.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 "MapViewController.h"
+#import "OthersFormViewController.h"
+
+NSString *const kSwitchBool = @"switchBool";
+NSString *const kSwitchCheck = @"switchCheck";
+NSString *const kStepCounter = @"stepCounter";
+NSString *const kSlider = @"slider";
+NSString *const kSegmentedControl = @"segmentedControl";
+NSString *const kCustom = @"custom";
+NSString *const kInfo = @"info";
+NSString *const kButton = @"button";
+NSString *const kImage = @"image";
+NSString *const kButtonLeftAligned = @"buttonLeftAligned";
+NSString *const kButtonWithSegueId = @"buttonWithSegueId";
+NSString *const kButtonWithSegueClass = @"buttonWithSegueClass";
+NSString *const kButtonWithNibName = @"buttonWithNibName";
+NSString *const kButtonWithStoryboardId = @"buttonWithStoryboardId";
+
+
+@implementation OthersFormViewController
+
+
+-(instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+-(instancetype)init
+{
+    self = [super init];
+    if (self){
+        [self initializeForm];
+    }
+    return self;
+}
+
+-(void)initializeForm
+{
+    XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"Other Cells"];
+    XLFormSectionDescriptor * section;
+    
+    // Basic Information
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Other Cells"];
+    section.footerTitle = @"OthersFormViewController.h";
+    [form addFormSection:section];
+    
+    // Switch
+    XLFormRowDescriptor * row = [XLFormRowDescriptor formRowDescriptorWithTag:kSwitchBool rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Switch"];
+    [row.cellConfigAtConfigure setObject:[UIColor redColor] forKey:@"switchControl.onTintColor"];
+    [section addFormRow:row];
+    // check
+    [section addFormRow:[XLFormRowDescriptor formRowDescriptorWithTag:kSwitchCheck rowType:XLFormRowDescriptorTypeBooleanCheck title:@"Check"]];
+    
+    // step counter
+    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
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSegmentedControl rowType:XLFormRowDescriptorTypeSelectorSegmentedControl title:@"Fruits"];
+    row.selectorOptions = @[@"Apple", @"Orange", @"Pear"];
+    row.value = @"Pear";
+    [section addFormRow:row];
+    
+    
+    // Slider
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSlider rowType:XLFormRowDescriptorTypeSlider title:@"Slider"];
+    row.value = @(30);
+    [row.cellConfigAtConfigure setObject:@(100) forKey:@"slider.maximumValue"];
+    [row.cellConfigAtConfigure setObject:@(10) forKey:@"slider.minimumValue"];
+    [row.cellConfigAtConfigure setObject:@(4) forKey:@"steps"];
+    [section addFormRow:row];
+    
+    // Image
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kImage rowType:XLFormRowDescriptorTypeImage title:@"Image"];
+    row.value = [UIImage imageNamed:@"default_avatar"];
+    [section addFormRow:row];
+
+    // Info cell
+    XLFormRowDescriptor *infoRowDescriptor = [XLFormRowDescriptor formRowDescriptorWithTag:kInfo rowType:XLFormRowDescriptorTypeInfo];
+    infoRowDescriptor.title = @"Version";
+    infoRowDescriptor.value = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"];
+    [section addFormRow:infoRowDescriptor];
+    
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Buttons"];
+    section.footerTitle = @"Blue buttons will show a message when Switch is ON";
+    [form addFormSection:section];
+    
+    // Button
+    XLFormRowDescriptor * buttonRow = [XLFormRowDescriptor formRowDescriptorWithTag:kButton rowType:XLFormRowDescriptorTypeButton title:@"Button"];
+    buttonRow.action.formSelector = @selector(didTouchButton:);
+    [section addFormRow:buttonRow];
+    
+    
+    // Left Button
+    XLFormRowDescriptor * buttonLeftAlignedRow = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonLeftAligned rowType:XLFormRowDescriptorTypeButton title:@"Button with Block"];
+    [buttonLeftAlignedRow.cellConfig setObject:@(NSTextAlignmentNatural) 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]){
+#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];
+    };
+    [section addFormRow:buttonLeftAlignedRow];
+    
+    // Another Left Button with segue
+    XLFormRowDescriptor * buttonLeftAlignedWithSegueRow = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonWithSegueClass rowType:XLFormRowDescriptorTypeButton title:@"Button with Segue Class"];
+    buttonLeftAlignedWithSegueRow.action.formSegueClass = NSClassFromString(@"UIStoryboardPushSegue");
+    buttonLeftAlignedWithSegueRow.action.viewControllerClass = [MapViewController class];
+    [section addFormRow:buttonLeftAlignedWithSegueRow];
+    
+    
+    // Button with SegueId
+    XLFormRowDescriptor * buttonWithSegueId = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonWithSegueClass rowType:XLFormRowDescriptorTypeButton title:@"Button with Segue Idenfifier"];
+    buttonWithSegueId.action.formSegueIdentifier = @"MapViewControllerSegue";
+    [section addFormRow:buttonWithSegueId];
+    
+    
+    // Another Button using Segue
+    XLFormRowDescriptor * buttonWithStoryboardId = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonWithStoryboardId rowType:XLFormRowDescriptorTypeButton title:@"Button with StoryboardId"];
+    buttonWithStoryboardId.action.viewControllerStoryboardId = @"MapViewController";
+    [section addFormRow:buttonWithStoryboardId];
+    
+    // Another Left Button with segue
+    XLFormRowDescriptor * buttonWithNibName = [XLFormRowDescriptor formRowDescriptorWithTag:kButtonWithNibName
+                                                                                    rowType:XLFormRowDescriptorTypeButton
+                                                                                      title:@"Button with NibName"];
+    buttonWithNibName.action.viewControllerNibName = @"MapViewController";
+    [section addFormRow:buttonWithNibName];
+    
+    self.form = form;
+}
+
+-(void)didTouchButton:(XLFormRowDescriptor *)sender
+{
+    if ([[sender.sectionDescriptor.formDescriptor formRowWithTag:kSwitchBool].value boolValue]){
+#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];
+}
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithTitle:@"Disable" style:UIBarButtonItemStylePlain
+                                                target:self
+                                                action:@selector(disableEnable:)];
+    barButton.possibleTitles = [NSSet setWithObjects:@"Disable", @"Enable", nil];
+    self.navigationItem.rightBarButtonItem = barButton;
+}
+
+-(void)disableEnable:(UIBarButtonItem *)button
+{
+    self.form.disabled = !self.form.disabled;
+    [button setTitle:(self.form.disabled ? @"Enable" : @"Disable")];
+    [self.tableView endEditing:YES];
+    [self.tableView reloadData];
+}
+
+
+@end

BIN
Examples/Objective-C/Examples/Others/XLForm-Boolean.gif


BIN
Examples/Objective-C/Examples/Others/XLForm-stepCounter.gif


+ 31 - 0
Examples/Objective-C/Examples/PredicateExamples/BasicPredicateViewController.h

@@ -0,0 +1,31 @@
+//
+//  BasicPredicateViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface BasicPredicateViewController : XLFormViewController
+
+@end

+ 84 - 0
Examples/Objective-C/Examples/PredicateExamples/BasicPredicateViewController.m

@@ -0,0 +1,84 @@
+//
+//  BasicPredicateViewController.m
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "BasicPredicateViewController.h"
+
+NSString *const khiderow = @"tag1";
+NSString *const khidesection = @"tag2";
+NSString *const ktext = @"tag3";
+
+@implementation BasicPredicateViewController
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+- (void)initializeForm
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Basic Predicates"];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"A Section"];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:khiderow rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Show next row"];
+    row.value = @0;
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:khidesection rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Show B Section"];
+    row.hidden = [NSString stringWithFormat:@"$%@==0", khiderow];
+    row.value = @0;
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"B Section"];
+    section.footerTitle = @"BasicPredicateViewController";
+    section.hidden = [NSString stringWithFormat:@"$%@==0", khidesection];
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:ktext rowType:XLFormRowDescriptorTypeText title:@""];
+    [row.cellConfigAtConfigure setObject:@"Gonna disappear soon!!" forKey:@"textField.placeholder"];
+    [section addFormRow:row];
+    
+    self.form = form;
+}
+
+@end

+ 31 - 0
Examples/Objective-C/Examples/PredicateExamples/BlogExampleViewController.h

@@ -0,0 +1,31 @@
+//
+//  BlogExampleViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface BlogExampleViewController : XLFormViewController
+
+@end

+ 106 - 0
Examples/Objective-C/Examples/PredicateExamples/BlogExampleViewController.m

@@ -0,0 +1,106 @@
+//
+//  BlogExampleViewController.m
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "BlogExampleViewController.h"
+
+NSString *const kHobbies = @"hobbies";
+NSString *const kSport = @"sport";
+NSString *const kFilm = @"films1";
+NSString *const kFilm2 = @"films2";
+NSString *const kMusic = @"music";
+
+@implementation BlogExampleViewController
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+- (void)initializeForm
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Blog Example: Hobbies"];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Hobbies"];
+    [form addFormSection:section];
+    
+    XLFormRowDescriptor* hobbyRow = [XLFormRowDescriptor formRowDescriptorWithTag:kHobbies
+                                                                          rowType:XLFormRowDescriptorTypeMultipleSelector
+                                                                            title:@"Select Hobbies"];
+    hobbyRow.selectorOptions = @[@"Sport", @"Music", @"Films"];
+    hobbyRow.value = @[];
+    [section addFormRow:hobbyRow];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Some more questions"];
+    section.hidden = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"$%@.value.@count == 0", hobbyRow]];
+    section.footerTitle = @"BlogExampleViewController.m";
+    [form addFormSection:section];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSport
+                                                rowType:XLFormRowDescriptorTypeTextView
+                                                  title:@"Your favourite sportsman?"];
+    row.hidden = [NSString stringWithFormat:@"NOT $%@.value contains 'Sport'", hobbyRow];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kFilm
+                                                rowType:XLFormRowDescriptorTypeTextView
+                                                  title:@"Your favourite film?"];
+    row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Films'", hobbyRow];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kFilm2
+                                                rowType:XLFormRowDescriptorTypeTextView
+                                                  title:@"Your favourite actor?"];
+    row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Films'", hobbyRow];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMusic
+                                                rowType:XLFormRowDescriptorTypeTextView
+                                                  title:@"Your favourite singer?"];
+    row.hidden = [NSString stringWithFormat:@"NOT $%@ contains 'Music'", hobbyRow];
+    [section addFormRow:row];
+    
+    self.form = form;
+}
+
+
+@end

+ 31 - 0
Examples/Objective-C/Examples/PredicateExamples/PredicateFormViewController.h

@@ -0,0 +1,31 @@
+//
+//  PredicateFormViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface PredicateFormViewController : XLFormViewController
+
+@end

+ 116 - 0
Examples/Objective-C/Examples/PredicateExamples/PredicateFormViewController.m

@@ -0,0 +1,116 @@
+//
+//  PredicateFormViewController.m
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+// 
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+NSString *const kPred = @"pred";
+NSString *const kPredDep = @"preddep";
+NSString *const kPredDep2 = @"preddep2";
+
+#import "PredicateFormViewController.h"
+
+@implementation PredicateFormViewController
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+- (void)initializeForm
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    XLFormRowDescriptor * pred, *pred3, *pred4;
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Predicates example"];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Independent rows"];
+    
+
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredDep rowType:XLFormRowDescriptorTypeAccount title:@"Text"];
+    [row.cellConfigAtConfigure setObject:@"Type disable" forKey:@"textField.placeholder"];
+    pred = row;
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPredDep2 rowType:XLFormRowDescriptorTypeInteger title:@"Integer"];
+    row.hidden = [NSString stringWithFormat:@"$switch==0"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"switch" rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"Boolean"];
+    row.value = @1;
+    pred3 = row;
+    [section addFormRow:row];
+    
+    [form addFormSection:section];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Dependent section"];
+    section.footerTitle = @"Type disable in the textfield, a number between 18 and 60 in the integer field or use the switch to disable the last row. By doing all three the last section will hide.\nThe integer field hides when the boolean switch is set to 0.";
+    [form addFormSection:section];
+    
+    // Predicate Disabling
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPred rowType:XLFormRowDescriptorTypeDateInline title:@"Disabled"];
+    row.value = [NSDate new];
+    [section addFormRow:row];
+    
+    row.disabled = [NSString stringWithFormat:@"$%@ contains[c] 'disable' OR ($%@.value between {18, 60}) OR ($%@.value == 0)", pred, kPredDep2, pred3];
+    //[NSPredicate predicateWithFormat:[NSString stringWithFormat:@"($%@.value contains[c] %%@) OR ($%@.value between {18, 60}) OR ($%@.value == 0)", pred, pred2, pred3],  @"disable"] ];
+    pred4 = row;
+
+    section.hidden = [NSPredicate predicateWithFormat:[NSString stringWithFormat:@"($%@.value contains[c] 'disable') AND ($%@.value between {18, 60}) AND ($%@.value == 0)", pred, kPredDep2, pred3]];
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"More predicates..."];
+    section.footerTitle = @"This row hides when the row of the previous section is disabled and the textfield in the first section contains \"out\"\n\nPredicateFormViewController.m";
+    [form addFormSection:section];
+    
+
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"thirds" rowType:XLFormRowDescriptorTypeAccount title:@"Account"];
+    [section addFormRow:row];
+    row.hidden = [NSString stringWithFormat:@"$%@.isDisabled == 1 AND $%@.value contains[c] 'Out'", pred4, pred];
+    
+    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:NSLocalizedString(@"Cancel", nil) style:UIAlertActionStyleCancel handler:nil]];
+        [weakself.navigationController presentViewController:alert animated:YES completion:nil];
+    };
+    
+    self.form = form;
+}
+
+@end

BIN
Examples/Objective-C/Examples/PredicateExamples/XLFormPredicates.gif


BIN
Examples/Objective-C/Examples/PredicateExamples/XLFormPredicatesBasic.gif


+ 34 - 0
Examples/Objective-C/Examples/RealExamples/NativeEventFormViewController.h

@@ -0,0 +1,34 @@
+//
+//  NativeEventNavigationViewController.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 "XLFormViewController.h"
+
+@interface NativeEventNavigationViewController : UINavigationController
+
+@end
+
+@interface NativeEventFormViewController : XLFormViewController
+
+@end

+ 263 - 0
Examples/Objective-C/Examples/RealExamples/NativeEventFormViewController.m

@@ -0,0 +1,263 @@
+//
+//  NativeEventNavigationViewController.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 "XLForm.h"
+#import "DateAndTimeValueTrasformer.h"
+#import "NativeEventFormViewController.h"
+
+
+@implementation NativeEventNavigationViewController
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    [self.view setTintColor:[UIColor redColor]];
+}
+
+@end
+
+@interface NativeEventFormViewController ()
+
+@end
+
+@implementation NativeEventFormViewController
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+- (void)initializeForm
+{
+    XLFormDescriptor * form;
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    form = [XLFormDescriptor formDescriptorWithTitle:@"Add Event"];
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    
+    // Title
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"Title" rowType:XLFormRowDescriptorTypeText];
+    [row.cellConfigAtConfigure setObject:@"Title" forKey:@"textField.placeholder"];
+    row.required = YES;
+    [section addFormRow:row];
+    
+    // Location
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"location" rowType:XLFormRowDescriptorTypeText];
+    [row.cellConfigAtConfigure setObject:@"Location" forKey:@"textField.placeholder"];
+    [section addFormRow:row];
+    
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    
+    // All-day
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"all-day" rowType:XLFormRowDescriptorTypeBooleanSwitch title:@"All-day"];
+    [section addFormRow:row];
+    
+    // Starts
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"starts" rowType:XLFormRowDescriptorTypeDateTimeInline title:@"Starts"];
+    row.value = [NSDate dateWithTimeIntervalSinceNow:60*60*24];
+    [section addFormRow:row];
+    
+    // Ends
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"ends" rowType:XLFormRowDescriptorTypeDateTimeInline title:@"Ends"];
+    row.value = [NSDate dateWithTimeIntervalSinceNow:60*60*25];
+    [section addFormRow:row];
+
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+
+    // Repeat
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"repeat" rowType:XLFormRowDescriptorTypeSelectorPush title:@"Repeat"];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Never"];
+    row.selectorTitle = @"Repeat";
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Never"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Every Day"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Every Week"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Every 2 Weeks"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Every Month"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(5) displayText:@"Every Year"],
+                            ];
+    [section addFormRow:row];
+
+
+
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    
+    // Alert
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"alert" rowType:XLFormRowDescriptorTypeSelectorPush title:@"Alert"];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"None"];
+    row.selectorTitle = @"Event Alert";
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"None"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"At time of event"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"5 minutes before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"15 minutes before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"30 minutes before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(5) displayText:@"1 hour before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(6) displayText:@"2 hours before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(7) displayText:@"1 day before"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(8) displayText:@"2 days before"],
+                            ];
+    [section addFormRow:row];
+
+
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+    
+    // Show As
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"showAs" rowType:XLFormRowDescriptorTypeSelectorPush title:@"Show As"];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Busy"];
+    row.selectorTitle = @"Show As";
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Busy"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Free"]];
+    [section addFormRow:row];
+
+    section = [XLFormSectionDescriptor formSection];
+    [form addFormSection:section];
+
+    // URL
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"url" rowType:XLFormRowDescriptorTypeURL];
+    [row.cellConfigAtConfigure setObject:@"URL" forKey:@"textField.placeholder"];
+    [section addFormRow:row];
+    
+    // Notes
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:@"notes" rowType:XLFormRowDescriptorTypeTextView];
+    [row.cellConfigAtConfigure setObject:@"Notes" forKey:@"textView.placeholder"];
+    [section addFormRow:row];
+    
+    
+    self.form = form;
+}
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel target:self action:@selector(cancelPressed:)];
+    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave target:self action:@selector(savePressed:)];
+}
+
+
+#pragma mark - XLFormDescriptorDelegate
+
+-(void)formRowDescriptorValueHasChanged:(XLFormRowDescriptor *)rowDescriptor oldValue:(id)oldValue newValue:(id)newValue
+{
+    [super formRowDescriptorValueHasChanged:rowDescriptor oldValue:oldValue newValue:newValue];
+    if ([rowDescriptor.tag isEqualToString:@"alert"]){
+        if ([[rowDescriptor.value valueData] isEqualToNumber:@(0)] == NO && [[oldValue valueData] isEqualToNumber:@(0)]){
+        
+            XLFormRowDescriptor * newRow = [rowDescriptor copy];
+            newRow.tag = @"secondAlert";
+            newRow.title = @"Second Alert";
+            [self.form addFormRow:newRow afterRow:rowDescriptor];
+        }
+        else if ([[oldValue valueData] isEqualToNumber:@(0)] == NO && [[newValue valueData] isEqualToNumber:@(0)]){
+            [self.form removeFormRowWithTag:@"secondAlert"];
+        }
+    }
+    else if ([rowDescriptor.tag isEqualToString:@"all-day"]){
+        XLFormRowDescriptor * startDateDescriptor = [self.form formRowWithTag:@"starts"];
+        XLFormRowDescriptor * endDateDescriptor = [self.form formRowWithTag:@"ends"];
+        XLFormDateCell * dateStartCell = (XLFormDateCell *)[[self.form formRowWithTag:@"starts"] cellForFormController:self];
+        XLFormDateCell * dateEndCell = (XLFormDateCell *)[[self.form formRowWithTag:@"ends"] cellForFormController:self];
+        if ([[rowDescriptor.value valueData] boolValue] == YES){
+            startDateDescriptor.valueTransformer = [DateValueTrasformer class];
+            endDateDescriptor.valueTransformer = [DateValueTrasformer class];
+            [dateStartCell setFormDatePickerMode:XLFormDateDatePickerModeDate];
+            [dateEndCell setFormDatePickerMode:XLFormDateDatePickerModeDate];
+        }
+        else{
+            startDateDescriptor.valueTransformer = [DateTimeValueTrasformer class];
+            endDateDescriptor.valueTransformer = [DateTimeValueTrasformer class];
+            [dateStartCell setFormDatePickerMode:XLFormDateDatePickerModeDateTime];
+            [dateEndCell setFormDatePickerMode:XLFormDateDatePickerModeDateTime];
+        }
+        [self updateFormRow:startDateDescriptor];
+        [self updateFormRow:endDateDescriptor];
+    }
+    else if ([rowDescriptor.tag isEqualToString:@"starts"]){
+        XLFormRowDescriptor * startDateDescriptor = [self.form formRowWithTag:@"starts"];
+        XLFormRowDescriptor * endDateDescriptor = [self.form formRowWithTag:@"ends"];
+        if ([startDateDescriptor.value compare:endDateDescriptor.value] == NSOrderedDescending) {
+            // startDateDescriptor is later than endDateDescriptor
+            endDateDescriptor.value =  [[NSDate alloc] initWithTimeInterval:(60*60*24) sinceDate:startDateDescriptor.value];
+            [endDateDescriptor.cellConfig removeObjectForKey:@"detailTextLabel.attributedText"];
+            [self updateFormRow:endDateDescriptor];
+        }
+    }
+    else if ([rowDescriptor.tag isEqualToString:@"ends"]){
+        XLFormRowDescriptor * startDateDescriptor = [self.form formRowWithTag:@"starts"];
+        XLFormRowDescriptor * endDateDescriptor = [self.form formRowWithTag:@"ends"];
+        XLFormDateCell * dateEndCell = (XLFormDateCell *)[endDateDescriptor cellForFormController:self];
+        if ([startDateDescriptor.value compare:endDateDescriptor.value] == NSOrderedDescending) {
+            // startDateDescriptor is later than endDateDescriptor
+            [dateEndCell update]; // force detailTextLabel update
+            NSDictionary *strikeThroughAttribute = [NSDictionary dictionaryWithObject:@1
+                                                                               forKey:NSStrikethroughStyleAttributeName];
+            NSAttributedString* strikeThroughText = [[NSAttributedString alloc] initWithString:dateEndCell.detailTextLabel.text attributes:strikeThroughAttribute];
+            [endDateDescriptor.cellConfig setObject:strikeThroughText forKey:@"detailTextLabel.attributedText"];
+            [self updateFormRow:endDateDescriptor];
+        }
+        else{
+            [endDateDescriptor.cellConfig removeObjectForKey:@"detailTextLabel.attributedText"];
+            [self updateFormRow:endDateDescriptor];
+        }
+    }
+}
+
+-(void)cancelPressed:(UIBarButtonItem * __unused)button
+{
+    [self dismissViewControllerAnimated:YES completion:nil];
+}
+
+
+-(void)savePressed:(UIBarButtonItem * __unused)button
+{
+    NSArray * validationErrors = [self formValidationErrors];
+    if (validationErrors.count > 0){
+        [self showFormValidationError:[validationErrors firstObject]];
+        return;
+    }
+    [self.tableView endEditing:YES];
+}
+
+
+
+@end

BIN
Examples/Objective-C/Examples/RealExamples/XLForm.gif


+ 30 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  CustomSelectorsFormViewController.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 "XLFormViewController.h"
+
+@interface CustomSelectorsFormViewController : XLFormViewController
+
+@end

+ 73 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.m

@@ -0,0 +1,73 @@
+//
+//  CustomSelectorsFormViewController.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 <MapKit/MapKit.h>
+#import "CLLocationValueTrasformer.h"
+#import "MapViewController.h"
+
+#import "CustomSelectorsFormViewController.h"
+
+NSString *const kSelectorMap = @"selectorMap";
+NSString *const kSelectorMapPopover = @"selectorMapPopover";
+
+@implementation CustomSelectorsFormViewController
+
+-(id)init
+{
+    self = [super init];
+    if (self) {
+        XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"Custom Selectors"];
+        XLFormSectionDescriptor * section;
+        XLFormRowDescriptor * row;
+        
+        // Basic Information
+        section = [XLFormSectionDescriptor formSection];
+        section.footerTitle = @"CustomSelectorsFormViewController.h";
+        [form addFormSection:section];
+        
+        
+        // Selector Push
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorMap rowType:XLFormRowDescriptorTypeSelectorPush title:@"Coordinate"];
+        row.action.viewControllerClass = [MapViewController class];
+        row.valueTransformer = [CLLocationValueTrasformer class];
+        row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+        [section addFormRow:row];
+        
+        if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
+            // Selector PopOver
+            row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorMapPopover rowType:XLFormRowDescriptorTypeSelectorPopover title:@"Coordinate PopOver"];
+            row.action.viewControllerClass = [MapViewController class];
+            row.valueTransformer = [CLLocationValueTrasformer class];
+            row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+            [section addFormRow:row];
+        }
+        
+        self.form = form;
+        
+    }
+    return self;
+}
+
+@end

+ 30 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.h

@@ -0,0 +1,30 @@
+//
+//  CLLocationValueTrasformer.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import <Foundation/Foundation.h>
+
+@interface CLLocationValueTrasformer : NSValueTransformer
+
+@end

+ 48 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.m

@@ -0,0 +1,48 @@
+//
+//  CLLocationValueTrasformer.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 <MapKit/MapKit.h>
+#import "CLLocationValueTrasformer.h"
+
+@implementation CLLocationValueTrasformer
+
++ (Class)transformedValueClass
+{
+    return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+    return NO;
+}
+
+- (id)transformedValue:(id)value
+{
+    if (!value) return nil;
+    CLLocation * location = (CLLocation *)value;
+    return [NSString stringWithFormat:@"%0.4f, %0.4f", location.coordinate.latitude, location.coordinate.longitude];
+}
+
+@end

+ 32 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.h

@@ -0,0 +1,32 @@
+//
+//  MapViewController.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 <UIKit/UIKit.h>
+
+@interface MapViewController : UIViewController <XLFormRowDescriptorViewController>
+
+@end

+ 108 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.m

@@ -0,0 +1,108 @@
+//
+//  MapViewController.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 "UIView+XLFormAdditions.h"
+#import <MapKit/MapKit.h>
+
+#import "MapViewController.h"
+
+
+@interface MapAnnotation : NSObject  <MKAnnotation>
+@end
+
+@implementation MapAnnotation
+@synthesize coordinate = _coordinate;
+-(void)setCoordinate:(CLLocationCoordinate2D)newCoordinate
+{
+    _coordinate = newCoordinate;
+}
+@end
+
+@interface MapViewController () <MKMapViewDelegate>
+
+@property (nonatomic) MKMapView * mapView;
+
+@end
+
+@implementation MapViewController
+
+@synthesize rowDescriptor = _rowDescriptor;
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Custom initialization
+    }
+    return self;
+}
+
+- (void)viewDidLoad
+{
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self.view addSubview:self.mapView];
+    self.mapView.delegate = self;
+    if (self.rowDescriptor.value){
+        [self.mapView setCenterCoordinate:((CLLocation *)self.rowDescriptor.value).coordinate];
+        self.title = [NSString stringWithFormat:@"%0.4f, %0.4f", self.mapView.centerCoordinate.latitude, self.mapView.centerCoordinate.longitude];
+        MapAnnotation *annotation = [[MapAnnotation alloc] init];
+        annotation.coordinate = self.mapView.centerCoordinate;
+        [self.mapView addAnnotation:annotation];
+    }
+}
+
+-(MKMapView *)mapView
+{
+    if (_mapView) return _mapView;
+    _mapView = [[MKMapView alloc] initWithFrame:self.view.bounds];
+    _mapView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
+    return _mapView;
+}
+
+#pragma mark - MKMapViewDelegate
+
+- (MKAnnotationView *)mapView:(MKMapView *)mapView
+            viewForAnnotation:(id <MKAnnotation>)annotation {
+    
+    MKPinAnnotationView *pinAnnotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation
+                                                                             reuseIdentifier:@"annotation"];
+    pinAnnotationView.pinColor = MKPinAnnotationColorRed;
+    pinAnnotationView.draggable = YES;
+    pinAnnotationView.animatesDrop = YES;
+    return pinAnnotationView;
+}
+
+- (void)mapView:(MKMapView *)mapView annotationView:(MKAnnotationView *)view didChangeDragState:(MKAnnotationViewDragState)newState
+   fromOldState:(MKAnnotationViewDragState)oldState
+{
+    if (newState == MKAnnotationViewDragStateEnding){
+        self.rowDescriptor.value = [[CLLocation alloc] initWithLatitude:view.annotation.coordinate.latitude longitude:view.annotation.coordinate.longitude];
+        self.title = [NSString stringWithFormat:@"%0.4f, %0.4f", view.annotation.coordinate.latitude, view.annotation.coordinate.longitude];
+    }
+}
+
+
+@end

+ 20 - 0
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.xib

@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+    </dependencies>
+    <objects>
+        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="MapViewController">
+            <connections>
+                <outlet property="view" destination="iN0-l3-epB" id="O5R-PM-tsI"/>
+            </connections>
+        </placeholder>
+        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+        <view contentMode="scaleToFill" id="iN0-l3-epB">
+            <rect key="frame" x="0.0" y="0.0" width="600" height="600"/>
+            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+        </view>
+    </objects>
+</document>

BIN
Examples/Objective-C/Examples/Selectors/CustomSelectors/XLFormRowViewController/XLForm-map-custom-selector.gif


+ 31 - 0
Examples/Objective-C/Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.h

@@ -0,0 +1,31 @@
+//
+//  DynamicSelectorsFormViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface DynamicSelectorsFormViewController : XLFormViewController
+
+@end

+ 94 - 0
Examples/Objective-C/Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.m

@@ -0,0 +1,94 @@
+//
+//  DynamicSelectorsFormViewController.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 "UsersTableViewController.h"
+#import "DynamicSelectorsFormViewController.h"
+
+NSString *const kSelectorUser = @"selectorUser";
+NSString *const kSelectorUserPopover = @"kSelectorUserPopover";
+
+@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
+{
+    self = [super init];
+    if (self) {
+        XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"Selectors"];
+        XLFormSectionDescriptor * section;
+        XLFormRowDescriptor * row;
+        
+        // Basic Information
+        section = [XLFormSectionDescriptor formSectionWithTitle:@"Dynamic Selectors"];
+        section.footerTitle = @"DynamicSelectorsFormViewController.h";
+        [form addFormSection:section];
+        
+        
+        // Selector Push
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorUser rowType:XLFormRowDescriptorTypeSelectorPush title:@"User"];
+        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];
+//        }
+        self.form = form;
+    }
+    return self;
+}
+
+- (UIStoryboard *)storyboardForRow:(XLFormRowDescriptor *)formRow
+{
+    return [UIStoryboard storyboardWithName:@"iPhoneStoryboard" bundle:nil];
+}
+
+@end

+ 34 - 0
Examples/Objective-C/Examples/Selectors/DynamicSelector/UsersTableViewController.h

@@ -0,0 +1,34 @@
+//
+//  UsersTableViewController.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 "XLFormRowDescriptor.h"
+#import "XLRemoteDataStoreController.h"
+
+@interface UsersTableViewController : XLRemoteDataStoreController <XLFormRowDescriptorViewController, XLFormRowDescriptorPopoverViewController>
+
+@property BOOL isSearchResultsController;
+@property NSLayoutConstraint *topConstraint;
+
+@end

+ 255 - 0
Examples/Objective-C/Examples/Selectors/DynamicSelector/UsersTableViewController.m

@@ -0,0 +1,255 @@
+//
+//  UsersTableViewController.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 "UsersTableViewController.h"
+#import "HTTPSessionManager.h"
+
+// AFNetworking
+#import <AFNetworking/UIImageView+AFNetworking.h>
+
+
+@interface UserCell : UITableViewCell
+
+@property (nonatomic) UIImageView * userImage;
+@property (nonatomic) UILabel * userName;
+
+@end
+
+@implementation UserCell
+
+@synthesize userImage = _userImage;
+@synthesize userName  = _userName;
+
+- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
+{
+    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
+    if (self) {
+        // Initialization code
+        
+        [self.contentView addSubview:self.userImage];
+        [self.contentView addSubview:self.userName];
+        
+        [self.contentView addConstraints:[self layoutConstraints]];
+    }
+    return self;
+}
+
+- (void)setSelected:(BOOL)selected animated:(BOOL)animated
+{
+    [super setSelected:selected animated:animated];
+    
+    // Configure the view for the selected state
+}
+
+#pragma mark - Views
+
+-(UIImageView *)userImage
+{
+    if (_userImage) return _userImage;
+    _userImage = [UIImageView new];
+    [_userImage setTranslatesAutoresizingMaskIntoConstraints:NO];
+    _userImage.layer.masksToBounds = YES;
+    _userImage.layer.cornerRadius = 10.0f;
+    return _userImage;
+}
+
+-(UILabel *)userName
+{
+    if (_userName) return _userName;
+    _userName = [UILabel new];
+    [_userName setTranslatesAutoresizingMaskIntoConstraints:NO];
+    _userName.font = [UIFont fontWithName:@"HelveticaNeue" size:15.f];
+    
+    return _userName;
+}
+
+#pragma mark - Layout Constraints
+
+-(NSArray *)layoutConstraints{
+    
+    NSMutableArray * result = [NSMutableArray array];
+    
+    NSDictionary * views = @{ @"image": self.userImage,
+                              @"name": self.userName};
+    
+    
+    NSDictionary *metrics = @{@"imgSize":@50.0,
+                              @"margin" :@12.0};
+    
+    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[image(imgSize)]-[name]"
+                                                                        options:NSLayoutFormatAlignAllTop
+                                                                        metrics:metrics
+                                                                          views:views]];
+    
+    [result addObjectsFromArray:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|-(margin)-[image(imgSize)]"
+                                                                        options:0
+                                                                        metrics:metrics
+                                                                          views:views]];
+    
+    return result;
+}
+
+
+@end
+
+
+@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";
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initialize];
+    }
+    return self;
+}
+
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if(self)
+    {
+        [self initialize];
+    }
+    
+    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];
+    [self.tableView registerClass:[UserCell class] forCellReuseIdentifier:kCellIdentifier];
+    self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
+    
+    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
+
+- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
+    UserCell *cell = (UserCell *) [tableView dequeueReusableCellWithIdentifier:kCellIdentifier forIndexPath: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;
+    
+    return cell;
+}
+
+#pragma mark - UITableViewDelegate
+
+- (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    return 73.0f;
+}
+
+-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    NSDictionary *dataItem = [self.dataStore dataAtIndexPath:indexPath];
+
+    self.rowDescriptor.value = dataItem;
+    
+    if (self.popoverController) {
+        [self.popoverController dismissPopoverAnimated:YES];
+        [self.popoverController.delegate popoverControllerDidDismissPopover:self.popoverController];
+    } else if ([self.parentViewController isKindOfClass:[UINavigationController class]]) {
+        [self.navigationController popViewControllerAnimated:YES];
+    } else if ([self.presentingViewController isKindOfClass:[UsersTableViewController class]]) {
+        [[self.presentingViewController navigationController] popViewControllerAnimated:YES];
+    }
+}
+
+#pragma mark - XLDataLoaderDelegate
+
+-(AFHTTPSessionManager *)sessionManagerForDataLoader:(XLDataLoader *)dataLoader
+{
+    return [HTTPSessionManager sharedClient];
+}
+
+#pragma mark - UISearchController
+
+-(UISearchController *)searchController
+{
+    if (_searchController) return _searchController;
+    
+    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;
+}
+
+
+-(UsersTableViewController *)searchResultController
+{
+    if (_searchResultController) return _searchResultController;
+    UsersTableViewController *usersViewController = [[UsersTableViewController alloc] init];
+    usersViewController.rowDescriptor = self.rowDescriptor;
+    _searchResultController = usersViewController;
+    _searchResultController.dataLoader.limit = 0; // no paging in search result
+    _searchResultController.isSearchResultsController = YES;
+    return _searchResultController;
+}
+
+@end

BIN
Examples/Objective-C/Examples/Selectors/DynamicSelector/XLForm-dynamic-custom-selector.gif


+ 32 - 0
Examples/Objective-C/Examples/Selectors/HTTPSessionManager.h

@@ -0,0 +1,32 @@
+//
+//  HTTPSessionManager.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 "AFHTTPSessionManager.h"
+
+@interface HTTPSessionManager : AFHTTPSessionManager
+
++ (HTTPSessionManager *)sharedClient;
+
+@end

+ 45 - 0
Examples/Objective-C/Examples/Selectors/HTTPSessionManager.m

@@ -0,0 +1,45 @@
+//
+//  HTTPSessionManager.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 "HTTPSessionManager.h"
+
+@implementation HTTPSessionManager
+
+// Server Base URL
+static NSString * const APIBaseURLString = @"http://obscure-refuge-3149.herokuapp.com";
+
++ (instancetype)sharedClient {
+    static HTTPSessionManager *_sharedClient = nil;
+    static dispatch_once_t onceToken;
+    dispatch_once(&onceToken, ^{
+        _sharedClient = [[HTTPSessionManager alloc] initWithBaseURL:[NSURL URLWithString:APIBaseURLString]];
+        [_sharedClient.reachabilityManager startMonitoring];
+        _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
+    });
+    
+    return _sharedClient;
+}
+
+@end

+ 11 - 0
Examples/Objective-C/Examples/Selectors/Helpers/Data/Model.xcdatamodeld/Model.xcdatamodel/contents

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="5064" systemVersion="13C1021" minimumToolsVersion="Xcode 4.3" macOSVersion="Automatic" iOSVersion="Automatic">
+    <entity name="User" representedClassName="User" syncable="YES">
+        <attribute name="userId" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
+        <attribute name="userImageURL" optional="YES" attributeType="String" syncable="YES"/>
+        <attribute name="userName" optional="YES" attributeType="String" syncable="YES"/>
+    </entity>
+    <elements>
+        <element name="User" positionX="-63" positionY="-18" width="128" height="88"/>
+    </elements>
+</model>

+ 31 - 0
Examples/Objective-C/Examples/Selectors/SelectorsFormViewController.h

@@ -0,0 +1,31 @@
+//
+//  SelectorsFormViewController.h
+//  XLForm ( https://github.com/xmartlabs/XLForm )
+//
+//  Copyright (c) 2015 Xmartlabs ( http://xmartlabs.com )
+//
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+
+#import "XLForm.h"
+#import "XLFormViewController.h"
+
+@interface SelectorsFormViewController : XLFormViewController
+
+@end

+ 389 - 0
Examples/Objective-C/Examples/Selectors/SelectorsFormViewController.m

@@ -0,0 +1,389 @@
+//
+//  SelectorsFormViewController.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 <MapKit/MapKit.h>
+#import "CLLocationValueTrasformer.h"
+#import "MapViewController.h"
+#import "CustomSelectorsFormViewController.h"
+#import "DynamicSelectorsFormViewController.h"
+#import "SelectorsFormViewController.h"
+
+NSString *const kSelectorPush = @"selectorPush";
+NSString *const kSelectorPopover = @"selectorPopover";
+NSString *const kSelectorActionSheet = @"selectorActionSheet";
+NSString *const kSelectorAlertView = @"selectorAlertView";
+NSString *const kSelectorLeftRight = @"selectorLeftRight";
+NSString *const kSelectorPushDisabled = @"selectorPushDisabled";
+NSString *const kSelectorActionSheetDisabled = @"selectorActionSheetDisabled";
+NSString *const kSelectorLeftRightDisabled = @"selectorLeftRightDisabled";
+NSString *const kSelectorPickerView = @"selectorPickerView";
+NSString *const kSelectorPickerViewInline = @"selectorPickerViewInline";
+NSString *const kMultipleSelector = @"multipleSelector";
+NSString *const kMultipleSelectorPopover = @"multipleSelectorPopover";
+NSString *const kDynamicSelectors = @"dynamicSelectors";
+NSString *const kCustomSelectors = @"customSelectors";
+NSString *const kPickerView = @"pickerView";
+NSString *const kSelectorWithSegueId = @"selectorWithSegueId";
+NSString *const kSelectorWithSegueClass = @"selectorWithSegueClass";
+NSString *const kSelectorWithNibName = @"selectorWithNibName";
+NSString *const kSelectorWithStoryboardId = @"selectorWithStoryboardId";
+
+#pragma mark - NSValueTransformer
+
+@interface NSArrayValueTrasformer : NSValueTransformer
+@end
+
+@implementation NSArrayValueTrasformer
+
++ (Class)transformedValueClass
+{
+    return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+    return NO;
+}
+
+- (id)transformedValue:(id)value
+{
+    if (!value) return nil;
+    if ([value isKindOfClass:[NSArray class]]){
+        NSArray * array = (NSArray *)value;
+        return [NSString stringWithFormat:@"%@ Item%@", @(array.count), array.count > 1 ? @"s" : @""];
+    }
+    if ([value isKindOfClass:[NSString class]])
+    {
+        return [NSString stringWithFormat:@"%@ - ;) - Transformed", value];
+    }
+    return nil;
+}
+
+@end
+
+
+@interface ISOLanguageCodesValueTranformer : NSValueTransformer
+@end
+
+@implementation ISOLanguageCodesValueTranformer
+
++ (Class)transformedValueClass
+{
+    return [NSString class];
+}
+
++ (BOOL)allowsReverseTransformation
+{
+    return NO;
+}
+
+- (id)transformedValue:(id)value
+{
+    if (!value) return nil;
+    if ([value isKindOfClass:[NSString class]]){
+        return [[NSLocale currentLocale] displayNameForKey:NSLocaleLanguageCode value:value];
+    }
+    return nil;
+}
+
+@end
+
+
+#pragma mark - SelectorsFormViewController
+
+@implementation SelectorsFormViewController
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (instancetype)init
+{
+    self = [super init];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+- (void)initializeForm
+{
+    XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"Selectors"];
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    // Basic Information
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Selectors"];
+    section.footerTitle = @"SelectorsFormViewController.h";
+    [form addFormSection:section];
+    
+    
+    // Selector Push
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorPush rowType:XLFormRowDescriptorTypeSelectorPush title:@"Push"];
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Option 1"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Option 5"]
+                            ];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"];
+    [section addFormRow:row];
+    
+    // Selector Popover
+    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorPopover rowType:XLFormRowDescriptorTypeSelectorPopover title:@"PopOver"];
+        row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+        row.value = @"Option 2";
+        [section addFormRow:row];
+    }
+    
+    // Selector Action Sheet
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorActionSheet rowType:XLFormRowDescriptorTypeSelectorActionSheet title:@"Sheet"];
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Option 1"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Option 5"]
+                            ];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"];
+    [section addFormRow:row];
+    
+    
+    
+    
+    // Selector Alert View
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorAlertView rowType:XLFormRowDescriptorTypeSelectorAlertView title:@"Alert View"];
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Option 1"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Option 5"]
+                            ];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"];
+    [section addFormRow:row];
+    
+    
+    
+    // Selector Left Right
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorLeftRight rowType:XLFormRowDescriptorTypeSelectorLeftRight title:@"Left Right"];
+    row.leftRightSelectorLeftOptionSelected = [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"];
+    
+    NSArray * rightOptions =  @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Right Option 1"],
+                                [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Right Option 2"],
+                                [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Right Option 3"],
+                                [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Right Option 4"],
+                                [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Right Option 5"]
+                                ];
+    
+    // create right selectors
+    NSMutableArray * leftRightSelectorOptions = [[NSMutableArray alloc] init];
+    NSMutableArray * mutableRightOptions = [rightOptions mutableCopy];
+    [mutableRightOptions removeObjectAtIndex:0];
+    XLFormLeftRightSelectorOption * leftRightSelectorOption = [XLFormLeftRightSelectorOption formLeftRightSelectorOptionWithLeftValue:[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Option 1"] httpParameterKey:@"option_1" rightOptions:mutableRightOptions];
+    [leftRightSelectorOptions addObject:leftRightSelectorOption];
+    
+    mutableRightOptions = [rightOptions mutableCopy];
+    [mutableRightOptions removeObjectAtIndex:1];
+    leftRightSelectorOption = [XLFormLeftRightSelectorOption formLeftRightSelectorOptionWithLeftValue:[XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"] httpParameterKey:@"option_2" rightOptions:mutableRightOptions];
+    leftRightSelectorOption.leftValueChangePolicy = XLFormLeftRightSelectorOptionLeftValueChangePolicyChooseFirstOption;
+    [leftRightSelectorOptions addObject:leftRightSelectorOption];
+    
+    mutableRightOptions = [rightOptions mutableCopy];
+    [mutableRightOptions removeObjectAtIndex:2];
+    leftRightSelectorOption = [XLFormLeftRightSelectorOption formLeftRightSelectorOptionWithLeftValue:[XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"]  httpParameterKey:@"option_3" rightOptions:mutableRightOptions];
+    leftRightSelectorOption.leftValueChangePolicy = XLFormLeftRightSelectorOptionLeftValueChangePolicyChooseLastOption;
+    [leftRightSelectorOptions addObject:leftRightSelectorOption];
+    
+    mutableRightOptions = [rightOptions mutableCopy];
+    [mutableRightOptions removeObjectAtIndex:3];
+    leftRightSelectorOption = [XLFormLeftRightSelectorOption formLeftRightSelectorOptionWithLeftValue:[XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"] httpParameterKey:@"option_4" rightOptions:mutableRightOptions];
+    [leftRightSelectorOptions addObject:leftRightSelectorOption];
+    
+    mutableRightOptions = [rightOptions mutableCopy];
+    [mutableRightOptions removeObjectAtIndex:4];
+    leftRightSelectorOption = [XLFormLeftRightSelectorOption formLeftRightSelectorOptionWithLeftValue:[XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Option 5"] httpParameterKey:@"option_5" rightOptions:mutableRightOptions];
+    [leftRightSelectorOptions addObject:leftRightSelectorOption];
+    
+    row.selectorOptions  = leftRightSelectorOptions;
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Right Option 4"];
+    [section addFormRow:row];
+    
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorPickerView rowType:XLFormRowDescriptorTypeSelectorPickerView title:@"Picker View"];
+    row.selectorOptions = @[[XLFormOptionsObject formOptionsObjectWithValue:@(0) displayText:@"Option 1"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(1) displayText:@"Option 2"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(2) displayText:@"Option 3"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"],
+                            [XLFormOptionsObject formOptionsObjectWithValue:@(4) displayText:@"Option 5"]
+                            ];
+    row.value = [XLFormOptionsObject formOptionsObjectWithValue:@(3) displayText:@"Option 4"];
+    [section addFormRow:row];
+    
+    
+    
+    // --------- Fixed Controls
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Fixed Controls"];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kPickerView rowType:XLFormRowDescriptorTypePicker];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    row.value = @"Option 1";
+    [section addFormRow:row];
+    
+    
+    
+    // --------- Inline Selectors
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Inline Selectors"];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultipleSelector rowType:XLFormRowDescriptorTypeSelectorPickerViewInline title:@"Inline Picker View"];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    row.value = @"Option 6";
+    [section addFormRow:row];
+    
+    // --------- MultipleSelector
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Multiple Selectors"];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultipleSelector rowType:XLFormRowDescriptorTypeMultipleSelector title:@"Multiple Selector"];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    row.value = @[@"Option 1", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    [section addFormRow:row];
+    
+    
+    // Multiple selector with value tranformer
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultipleSelector rowType:XLFormRowDescriptorTypeMultipleSelector title:@"Multiple Selector"];
+    row.selectorOptions = @[@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    row.value = @[@"Option 1", @"Option 3", @"Option 4", @"Option 5", @"Option 6"];
+    row.valueTransformer = [NSArrayValueTrasformer class];
+    [section addFormRow:row];
+    
+    
+    // Language multiple selector
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultipleSelector rowType:XLFormRowDescriptorTypeMultipleSelector title:@"Multiple Selector"];
+    row.selectorOptions = [NSLocale ISOLanguageCodes];
+    row.selectorTitle = @"Languages";
+    row.valueTransformer = [ISOLanguageCodesValueTranformer class];
+    row.value = [NSLocale preferredLanguages];
+    [section addFormRow:row];
+    
+    if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad){
+        // Language multiple selector popover
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:kMultipleSelectorPopover rowType:XLFormRowDescriptorTypeMultipleSelectorPopover title:@"Multiple Selector PopOver"];
+        row.selectorOptions = [NSLocale ISOLanguageCodes];
+        row.valueTransformer = [ISOLanguageCodesValueTranformer class];
+        row.value = [NSLocale preferredLanguages];
+        [section addFormRow:row];
+    }
+    
+    
+    // --------- Dynamic Selectors
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Dynamic Selectors"];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kDynamicSelectors rowType:XLFormRowDescriptorTypeButton title:@"Dynamic Selectors"];
+    row.action.viewControllerClass = [DynamicSelectorsFormViewController class];
+    [section addFormRow:row];
+    
+    // --------- Custom Selectors
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Custom Selectors"];
+    [form addFormSection:section];
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kCustomSelectors rowType:XLFormRowDescriptorTypeButton title:@"Custom Selectors"];
+    row.action.viewControllerClass = [CustomSelectorsFormViewController class];
+    [section addFormRow:row];
+    
+    
+    // --------- Selector definition types
+    
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Selectors"];
+    [form addFormSection:section];
+    
+    // selector with segue class
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorWithSegueClass rowType:XLFormRowDescriptorTypeSelectorPush title:@"Selector with Segue Class"];
+    row.action.formSegueClass = NSClassFromString(@"UIStoryboardPushSegue");
+    row.action.viewControllerClass = [MapViewController class];
+    row.valueTransformer = [CLLocationValueTrasformer class];
+    row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+    [section addFormRow:row];
+    
+    // selector with SegueId
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorWithSegueId rowType:XLFormRowDescriptorTypeSelectorPush title:@"Selector with Segue Identifier"];
+    row.action.formSegueIdentifier = @"MapViewControllerSegue";
+    row.valueTransformer = [CLLocationValueTrasformer class];
+    row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+    [section addFormRow:row];
+    
+    // selector using StoryboardId
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorWithStoryboardId rowType:XLFormRowDescriptorTypeSelectorPush title:@"Selector with StoryboardId"];
+    row.action.viewControllerStoryboardId = @"MapViewController";
+    row.valueTransformer = [CLLocationValueTrasformer class];
+    row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+    [section addFormRow:row];
+    
+    // selector with NibName
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kSelectorWithNibName rowType:XLFormRowDescriptorTypeSelectorPush title:@"Selector with NibName"];
+    row.action.viewControllerNibName = @"MapViewController";
+    row.valueTransformer = [CLLocationValueTrasformer class];
+    row.value = [[CLLocation alloc] initWithLatitude:-33 longitude:-56];
+    [section addFormRow:row];
+    
+    
+    
+    self.form = form;
+}
+
+
+-(UIStoryboard *)storyboardForRow:(XLFormRowDescriptor *)formRow
+{
+    return [UIStoryboard storyboardWithName:@"iPhoneStoryboard" bundle:nil];
+}
+
+
+-(void)viewDidLoad
+{
+    [super viewDidLoad];
+    UIBarButtonItem * barButton = [[UIBarButtonItem alloc] initWithTitle:@"Disable" style:UIBarButtonItemStylePlain
+                                                                  target:self
+                                                                  action:@selector(disableEnable:)];
+    barButton.possibleTitles = [NSSet setWithObjects:@"Disable", @"Enable", nil];
+    self.navigationItem.rightBarButtonItem = barButton;
+}
+
+-(void)disableEnable:(UIBarButtonItem *)button
+{
+    self.form.disabled = !self.form.disabled;
+    [button setTitle:(self.form.disabled ? @"Enable" : @"Disable")];
+    [self.tableView endEditing:YES];
+    [self.tableView reloadData];
+}
+
+
+
+@end

BIN
Examples/Objective-C/Examples/Selectors/XLForm-Selectors.gif


+ 335 - 0
Examples/Objective-C/Examples/StoryboardExample/iPhoneStoryboard.storyboard

@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="9059" systemVersion="15B42" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" initialViewController="p4n-1v-pzo">
+    <dependencies>
+        <deployment identifier="iOS"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="9049"/>
+    </dependencies>
+    <scenes>
+        <!--Navigation Controller-->
+        <scene sceneID="hSO-iI-kK3">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="p4n-1v-pzo" sceneMemberID="viewController">
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="SNt-hk-N3V">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <animations/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="cUg-F9-RF7" kind="relationship" relationship="rootViewController" id="Dli-gX-3ei"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="jqF-cF-u4f" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="117" y="56"/>
+        </scene>
+        <!--Others Form View Controller-->
+        <scene sceneID="dyJ-7m-RaD">
+            <objects>
+                <viewController storyboardIdentifier="OthersFormViewController" id="oQO-1z-ESS" customClass="OthersFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="oOp-1u-3hE"/>
+                        <viewControllerLayoutGuide type="bottom" id="HPb-Nx-E1G"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="wpr-wE-9nj">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="Hf0-cB-ORN"/>
+                    <connections>
+                        <segue destination="WMh-VN-FWi" kind="push" identifier="MapViewControllerSegue" id="wAD-tS-AFZ"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="7YZ-ZR-X81" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1533" y="-233"/>
+        </scene>
+        <!--Native Event Form View Controller-->
+        <scene sceneID="EjT-rm-U3h">
+            <objects>
+                <viewController id="vx5-lN-WwK" customClass="NativeEventFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Fbw-im-bwR"/>
+                        <viewControllerLayoutGuide type="bottom" id="QuR-kY-o5R"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="tun-QW-CGC">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" translatesAutoresizingMaskIntoConstraints="NO" id="JY7-WL-SnH">
+                                <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+                                <animations/>
+                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                            </tableView>
+                        </subviews>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstItem="JY7-WL-SnH" firstAttribute="leading" secondItem="tun-QW-CGC" secondAttribute="leading" id="bSe-SV-rx6"/>
+                            <constraint firstAttribute="trailing" secondItem="JY7-WL-SnH" secondAttribute="trailing" id="jLI-68-pSq"/>
+                            <constraint firstItem="QuR-kY-o5R" firstAttribute="top" secondItem="JY7-WL-SnH" secondAttribute="bottom" id="lUW-qG-LqV"/>
+                            <constraint firstItem="JY7-WL-SnH" firstAttribute="top" secondItem="tun-QW-CGC" secondAttribute="top" id="tu2-ah-L2P"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" id="Xti-ay-J1u"/>
+                    <connections>
+                        <outlet property="tableView" destination="JY7-WL-SnH" id="kPy-NX-IyW"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="zV0-mq-irv" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1120" y="-635"/>
+        </scene>
+        <!--Examples-->
+        <scene sceneID="wf7-ha-lXx">
+            <objects>
+                <viewController automaticallyAdjustsScrollViewInsets="NO" id="cUg-F9-RF7" customClass="ExamplesFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="kOR-67-djF"/>
+                        <viewControllerLayoutGuide type="bottom" id="0bE-2H-tqE"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="PO9-pF-A7O">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" translatesAutoresizingMaskIntoConstraints="NO" id="Lxj-Sb-kC6">
+                                <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                                <animations/>
+                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                            </tableView>
+                        </subviews>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstItem="Lxj-Sb-kC6" firstAttribute="top" secondItem="kOR-67-djF" secondAttribute="bottom" id="PT1-Xo-3Ql"/>
+                            <constraint firstAttribute="trailing" secondItem="Lxj-Sb-kC6" secondAttribute="trailing" id="brq-yF-WM8"/>
+                            <constraint firstItem="Lxj-Sb-kC6" firstAttribute="leading" secondItem="PO9-pF-A7O" secondAttribute="leading" id="d73-kq-kX4"/>
+                            <constraint firstItem="0bE-2H-tqE" firstAttribute="top" secondItem="Lxj-Sb-kC6" secondAttribute="bottom" id="ltM-g9-Dgm"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Examples" id="sEr-D1-cU5"/>
+                    <connections>
+                        <outlet property="tableView" destination="Lxj-Sb-kC6" id="IS5-OZ-KBo"/>
+                        <segue destination="oQO-1z-ESS" kind="push" identifier="OthersFormViewControllerSegue" id="ulP-FP-rk3"/>
+                        <segue destination="G68-Ra-1fb" kind="push" identifier="SelectorsFormViewControllerSegue" id="vhA-cV-A02"/>
+                        <segue destination="K9D-4c-9eZ" kind="modal" identifier="NativeEventNavigationViewControllerSegue" id="Iie-Js-Izx"/>
+                        <segue destination="Kiw-nF-jv7" kind="push" identifier="ValidationExamplesFormViewControllerSegue" id="VKe-Ir-Fiu"/>
+                        <segue destination="OG6-Tc-1SC" kind="push" identifier="PredicateFormViewControllerSegue" id="Wwg-e9-gLq"/>
+                        <segue destination="pO0-sS-Tes" kind="push" identifier="BlogExampleViewSegue" id="a28-Gm-Iku"/>
+                        <segue destination="JL7-uU-kWK" kind="push" identifier="BasicPredicateViewControllerSegue" id="SGg-Ve-bng"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="1V5-DZ-WfF" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="527" y="56"/>
+        </scene>
+        <!--Blog Example View Controller-->
+        <scene sceneID="Vn0-9y-5bc">
+            <objects>
+                <viewController id="pO0-sS-Tes" customClass="BlogExampleViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="gjZ-Jv-Awa"/>
+                        <viewControllerLayoutGuide type="bottom" id="scM-da-Sg0"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="hrV-fb-58s">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="RJB-cz-SnF"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Fvo-wr-5Ca" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="167" y="1151"/>
+        </scene>
+        <!--Validation Examples-->
+        <scene sceneID="z2I-Nk-y9W">
+            <objects>
+                <viewController id="Kiw-nF-jv7" customClass="ValidationExamplesFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="AG9-N9-2qp"/>
+                        <viewControllerLayoutGuide type="bottom" id="xtJ-Wo-mhU"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="1Ol-Ra-Ysg">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <subviews>
+                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="default" rowHeight="44" sectionHeaderHeight="10" sectionFooterHeight="10" translatesAutoresizingMaskIntoConstraints="NO" id="Fty-3j-BeF">
+                                <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
+                                <animations/>
+                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                            </tableView>
+                        </subviews>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                        <constraints>
+                            <constraint firstItem="xtJ-Wo-mhU" firstAttribute="top" secondItem="Fty-3j-BeF" secondAttribute="bottom" id="CbV-4f-RzP"/>
+                            <constraint firstItem="Fty-3j-BeF" firstAttribute="top" secondItem="AG9-N9-2qp" secondAttribute="bottom" constant="-64" id="Pdw-VG-qcc"/>
+                            <constraint firstAttribute="trailing" secondItem="Fty-3j-BeF" secondAttribute="trailing" id="nPd-m1-CWF"/>
+                            <constraint firstItem="Fty-3j-BeF" firstAttribute="leading" secondItem="1Ol-Ra-Ysg" secondAttribute="leading" id="qUB-l2-4IG"/>
+                        </constraints>
+                    </view>
+                    <navigationItem key="navigationItem" title="Validation Examples" id="apf-4a-VpV">
+                        <barButtonItem key="rightBarButtonItem" title="Validate" id="Thm-OY-hsk"/>
+                    </navigationItem>
+                    <connections>
+                        <outlet property="tableView" destination="Fty-3j-BeF" id="Rck-sk-OHi"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="VFT-Og-STO" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="566" y="938"/>
+        </scene>
+        <!--Predicate Form View Controller-->
+        <scene sceneID="a9p-C8-g8y">
+            <objects>
+                <viewController id="OG6-Tc-1SC" customClass="PredicateFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="2YH-dK-JXQ"/>
+                        <viewControllerLayoutGuide type="bottom" id="Lsg-dH-McH"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="6EZ-O7-FjX">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="Lsd-xH-7IN"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="rZL-10-YZn" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="956" y="924"/>
+        </scene>
+        <!--Selectors Form View Controller-->
+        <scene sceneID="KYK-TX-8rm">
+            <objects>
+                <viewController id="G68-Ra-1fb" customClass="SelectorsFormViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="Z21-Qr-DQ8"/>
+                        <viewControllerLayoutGuide type="bottom" id="CTu-Y5-7Qw"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="bNj-SD-83w">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="Buo-Af-6Q1"/>
+                    <connections>
+                        <segue destination="WMh-VN-FWi" kind="push" identifier="MapViewControllerSegue" id="Mtw-x2-E0b"/>
+                    </connections>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="8fu-YK-6qz" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1346" y="533"/>
+        </scene>
+        <!--Map View Controller-->
+        <scene sceneID="tAS-lK-35t">
+            <objects>
+                <viewController storyboardIdentifier="MapViewController" id="WMh-VN-FWi" customClass="MapViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="9jO-04-Lp1"/>
+                        <viewControllerLayoutGuide type="bottom" id="cgQ-Vs-ICN"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="JjC-E5-SyY">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="BjG-Bq-0lD"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="LmS-YR-mFY" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="1789" y="533"/>
+        </scene>
+        <!--Native Event Navigation View Controller-->
+        <scene sceneID="mNb-be-ApA">
+            <objects>
+                <navigationController automaticallyAdjustsScrollViewInsets="NO" id="K9D-4c-9eZ" customClass="NativeEventNavigationViewController" sceneMemberID="viewController">
+                    <toolbarItems/>
+                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="fO3-V7-XXu">
+                        <rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
+                        <autoresizingMask key="autoresizingMask"/>
+                        <animations/>
+                    </navigationBar>
+                    <nil name="viewControllers"/>
+                    <connections>
+                        <segue destination="vx5-lN-WwK" kind="relationship" relationship="rootViewController" id="gie-et-cUW"/>
+                    </connections>
+                </navigationController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="eqB-vl-BzH" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="586" y="-654"/>
+        </scene>
+        <!--Basic Predicate View Controller-->
+        <scene sceneID="pD4-sm-x3a">
+            <objects>
+                <viewController id="JL7-uU-kWK" customClass="BasicPredicateViewController" sceneMemberID="viewController">
+                    <layoutGuides>
+                        <viewControllerLayoutGuide type="top" id="OQP-pW-kNp"/>
+                        <viewControllerLayoutGuide type="bottom" id="2b4-gN-85p"/>
+                    </layoutGuides>
+                    <view key="view" contentMode="scaleToFill" id="NZg-t1-g19">
+                        <rect key="frame" x="0.0" y="64" width="320" height="504"/>
+                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+                        <animations/>
+                        <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
+                    </view>
+                    <extendedEdge key="edgesForExtendedLayout" bottom="YES"/>
+                    <navigationItem key="navigationItem" id="1lh-jZ-lIV"/>
+                </viewController>
+                <placeholder placeholderIdentifier="IBFirstResponder" id="Tlw-q2-pcu" userLabel="First Responder" sceneMemberID="firstResponder"/>
+            </objects>
+            <point key="canvasLocation" x="-159" y="1151"/>
+        </scene>
+        <!--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"/>
+                                <animations/>
+                                <color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
+                            </tableView>
+                        </subviews>
+                        <animations/>
+                        <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>
+    <inferredMetricsTieBreakers>
+        <segue reference="Mtw-x2-E0b"/>
+    </inferredMetricsTieBreakers>
+</document>

+ 30 - 0
Examples/Objective-C/Examples/UICustomization/UICustomizationFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  UICustomizationFormViewController.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 "XLFormViewController.h"
+
+@interface UICustomizationFormViewController : XLFormViewController
+
+@end

+ 90 - 0
Examples/Objective-C/Examples/UICustomization/UICustomizationFormViewController.m

@@ -0,0 +1,90 @@
+//
+//  UICustomizationFormViewController.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 "XLForm.h"
+#import "UICustomizationFormViewController.h"
+
+@implementation UICustomizationFormViewController
+
+- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
+{
+    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
+    if (self) {
+        // Custom initialization
+        
+        XLFormDescriptor * form = [XLFormDescriptor formDescriptorWithTitle:@"UI Customization"];
+        XLFormSectionDescriptor * section;
+        XLFormRowDescriptor * row;
+        
+        
+        // Section
+        section = [XLFormSectionDescriptor formSection];
+        [form addFormSection:section];
+        
+        // Name
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:@"Name" rowType:XLFormRowDescriptorTypeText title:@"Name"];
+        // change the background color
+        [row.cellConfigAtConfigure setObject:[UIColor greenColor] forKey:@"backgroundColor"];
+        // font
+        [row.cellConfig setObject:[UIFont fontWithName:@"Helvetica" size:30] forKey:@"textLabel.font"];
+        // background color
+        [row.cellConfig setObject:[UIColor grayColor] forKey:@"textField.backgroundColor"];
+        // font
+        [row.cellConfig setObject:[UIFont fontWithName:@"Helvetica" size:25] forKey:@"textField.font"];
+        // alignment
+        [row.cellConfig setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+        [section addFormRow:row];
+        
+        
+        // Section
+        section = [XLFormSectionDescriptor formSection];
+        [form addFormSection:section];
+        
+        //Button
+        row = [XLFormRowDescriptor formRowDescriptorWithTag:@"Button" rowType:XLFormRowDescriptorTypeButton title:@"Button"];
+        [row.cellConfigAtConfigure setObject:[UIColor purpleColor] forKey:@"backgroundColor"];
+        [row.cellConfig setObject:[UIColor whiteColor] forKey:@"textLabel.color"];
+        [row.cellConfig setObject:[UIFont fontWithName:@"Helvetica" size:40] forKey:@"textLabel.font"];
+        [section addFormRow:row];
+        
+        self.form = form;
+    }
+    return self;
+}
+
+
+-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
+{
+    // change cell height of a particular cell
+    if ([[self.form formRowAtIndex:indexPath].tag isEqualToString:@"Name"]){
+        return 60.0;
+    }
+    else if ([[self.form formRowAtIndex:indexPath].tag isEqualToString:@"Button"]){
+        return 100.0;
+    }
+    return [super tableView:tableView heightForRowAtIndexPath:indexPath];
+}
+
+@end

+ 30 - 0
Examples/Objective-C/Examples/Validations/ValidationExamplesFormViewController.h

@@ -0,0 +1,30 @@
+//
+//  ValidationExamplesFormViewController.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 "XLFormViewController.h"
+
+@interface ValidationExamplesFormViewController : XLFormViewController
+
+@end

+ 160 - 0
Examples/Objective-C/Examples/Validations/ValidationExamplesFormViewController.m

@@ -0,0 +1,160 @@
+//
+//  ValidationExamplesFormViewController.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 "XLForm.h"
+#import "ValidationExamplesFormViewController.h"
+
+@implementation ValidationExamplesFormViewController
+
+NSString * const kValidationName = @"kName";
+NSString * const kValidationEmail = @"kEmail";
+NSString * const kValidationPassword = @"kPassword";
+NSString * const kValidationInteger = @"kInteger";
+
+
+- (instancetype)initWithCoder:(NSCoder *)coder
+{
+    self = [super initWithCoder:coder];
+    if (self) {
+        [self initializeForm];
+    }
+    return self;
+}
+
+
+-(void)initializeForm
+{
+    XLFormDescriptor * formDescriptor = [XLFormDescriptor formDescriptorWithTitle:@"Text Fields"];
+    XLFormSectionDescriptor * section;
+    XLFormRowDescriptor * row;
+    
+    // Name Section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Required"];
+    [formDescriptor addFormSection:section];
+    
+    // Name
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kValidationName rowType:XLFormRowDescriptorTypeText title:@"Name"];
+    [row.cellConfigAtConfigure setObject:@"Required..." forKey:@"textField.placeholder"];
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    row.required = YES;
+    row.value = @"Martin";
+    [section addFormRow:row];
+    
+    // Email Section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Email"];
+    [formDescriptor addFormSection:section];
+
+    // Email
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kValidationEmail rowType:XLFormRowDescriptorTypeText title:@"Email"];
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    row.required = NO;
+    row.value = @"not valid email";
+    [row addValidator:[XLFormValidator emailValidator]];
+    [section addFormRow:row];
+    
+    // password Section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Password"];
+    section.footerTitle = @"between 6 and 32 charachers, 1 alphanumeric and 1 numeric";
+    [formDescriptor addFormSection:section];
+    
+    // Password
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kValidationPassword rowType:XLFormRowDescriptorTypePassword title:@"Password"];
+    [row.cellConfigAtConfigure setObject:@"Required..." forKey:@"textField.placeholder"];
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    row.required = YES;
+    [row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"At least 6, max 32 characters" regex:@"^(?=.*\\d)(?=.*[A-Za-z]).{6,32}$"]];
+    [section addFormRow:row];
+    
+    // number Section
+    section = [XLFormSectionDescriptor formSectionWithTitle:@"Validation Numbers"];
+    section.footerTitle = @"greater than 50 and less than 100";
+    [formDescriptor addFormSection:section];
+    
+    // Integer
+    row = [XLFormRowDescriptor formRowDescriptorWithTag:kValidationInteger rowType:XLFormRowDescriptorTypeInteger title:@"Integer"];
+    [row.cellConfigAtConfigure setObject:@"Required..." forKey:@"textField.placeholder"];
+    [row.cellConfigAtConfigure setObject:@(NSTextAlignmentRight) forKey:@"textField.textAlignment"];
+    row.required = YES;
+    [row addValidator:[XLFormRegexValidator formRegexValidatorWithMsg:@"greater than 50 and less than 100" regex:@"^([5-9][0-9]|100)$"]];
+    [section addFormRow:row];
+    
+    self.form = formDescriptor;
+}
+
+
+- (void)viewDidLoad {
+    [super viewDidLoad];
+    // Do any additional setup after loading the view.
+    [self.navigationItem.rightBarButtonItem setTarget:self];
+    [self.navigationItem.rightBarButtonItem setAction:@selector(validateForm:)];
+}
+
+#pragma mark - actions
+
+-(void)validateForm:(UIBarButtonItem *)buttonItem
+{
+    NSArray * array = [self formValidationErrors];
+    [array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
+        XLFormValidationStatus * validationStatus = [[obj userInfo] objectForKey:XLValidationStatusErrorKey];
+        if ([validationStatus.rowDescriptor.tag isEqualToString:kValidationName]){
+            UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:[self.form indexPathOfFormRow:validationStatus.rowDescriptor]];
+            cell.backgroundColor = [UIColor orangeColor];
+            [UIView animateWithDuration:0.3 animations:^{
+                cell.backgroundColor = [UIColor whiteColor];
+            }];
+        }
+        else if ([validationStatus.rowDescriptor.tag isEqualToString:kValidationEmail]){
+            UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:[self.form indexPathOfFormRow:validationStatus.rowDescriptor]];
+            [self animateCell:cell];
+        }
+        else if ([validationStatus.rowDescriptor.tag isEqualToString:kValidationPassword]){
+            UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:[self.form indexPathOfFormRow:validationStatus.rowDescriptor]];
+            [self animateCell:cell];
+        }
+        else if ([validationStatus.rowDescriptor.tag isEqualToString:kValidationInteger]){
+            UITableViewCell * cell = [self.tableView cellForRowAtIndexPath:[self.form indexPathOfFormRow:validationStatus.rowDescriptor]];
+            [self animateCell:cell];
+        }
+    }];
+}
+
+
+#pragma mark - Helper
+
+-(void)animateCell:(UITableViewCell *)cell
+{
+    CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
+    animation.keyPath = @"position.x";
+    animation.values =  @[ @0, @20, @-20, @10, @0];
+    animation.keyTimes = @[@0, @(1 / 6.0), @(3 / 6.0), @(5 / 6.0), @1];
+    animation.duration = 0.3;
+    animation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
+    animation.additive = YES;
+    
+    [cell.layer addAnimation:animation forKey:@"shake"];
+}
+
+
+@end

+ 22 - 0
Examples/Objective-C/Inline Segmented/XLFormInlineSegmentedCell.h

@@ -0,0 +1,22 @@
+//
+//  XLFormInlineSegmentedCell.h
+//  XLForm
+//
+//  Created by mathias Claassen on 16/12/15.
+//  Copyright © 2015 Xmartlabs. All rights reserved.
+//
+
+#import <XLForm/XLForm.h>
+
+extern NSString * const XLFormRowDescriptorTypeSegmentedInline;
+extern NSString * const XLFormRowDescriptorTypeSegmentedControl;
+
+@interface XLFormInlineSegmentedCell : XLFormBaseCell
+
+@end
+
+
+@interface XLFormInlineSegmentedControl : XLFormBaseCell<XLFormInlineRowDescriptorCell>
+
+@property (strong, nonatomic) UISegmentedControl* segmentedControl;
+@end

+ 194 - 0
Examples/Objective-C/Inline Segmented/XLFormInlineSegmentedCell.m

@@ -0,0 +1,194 @@
+//
+//  XLFormInlineSegmentedCell.m
+//  XLForm
+//
+//  Created by mathias Claassen on 16/12/15.
+//  Copyright © 2015 Xmartlabs. All rights reserved.
+//
+
+#import "XLFormInlineSegmentedCell.h"
+
+NSString * const XLFormRowDescriptorTypeSegmentedInline = @"XLFormRowDescriptorTypeSegmentedInline";
+NSString * const XLFormRowDescriptorTypeSegmentedControl = @"XLFormRowDescriptorTypeSegmentedControl";
+
+@implementation XLFormInlineSegmentedCell
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:[XLFormInlineSegmentedCell class] forKey:XLFormRowDescriptorTypeSegmentedInline];
+    [XLFormViewController.inlineRowDescriptorTypesForRowDescriptorTypes setObject:XLFormRowDescriptorTypeSegmentedControl forKey:XLFormRowDescriptorTypeSegmentedInline];
+}
+
+- (BOOL)canBecomeFirstResponder
+{
+    return YES;
+}
+
+-(BOOL)becomeFirstResponder
+{
+    if (self.isFirstResponder){
+        return [super becomeFirstResponder];
+    }
+    BOOL result = [super becomeFirstResponder];
+    if (result){
+        XLFormRowDescriptor * inlineRowDescriptor = [XLFormRowDescriptor formRowDescriptorWithTag:nil rowType:[XLFormViewController inlineRowDescriptorTypesForRowDescriptorTypes][self.rowDescriptor.rowType]];
+        UITableViewCell<XLFormDescriptorCell> * cell = [inlineRowDescriptor cellForFormController:self.formViewController];
+        NSAssert([cell conformsToProtocol:@protocol(XLFormInlineRowDescriptorCell)], @"inline cell must conform to XLFormInlineRowDescriptorCell");
+        UITableViewCell<XLFormInlineRowDescriptorCell> * inlineCell = (UITableViewCell<XLFormInlineRowDescriptorCell> *)cell;
+        inlineCell.inlineRowDescriptor = self.rowDescriptor;
+        [self.rowDescriptor.sectionDescriptor addFormRow:inlineRowDescriptor afterRow:self.rowDescriptor];
+        [self.formViewController ensureRowIsVisible:inlineRowDescriptor];
+    }
+    return result;
+}
+
+-(BOOL)resignFirstResponder
+{
+    if (![self isFirstResponder]) {
+        return [super resignFirstResponder];
+    }
+    NSIndexPath * selectedRowPath = [self.formViewController.form indexPathOfFormRow:self.rowDescriptor];
+    NSIndexPath * nextRowPath = [NSIndexPath indexPathForRow:selectedRowPath.row + 1 inSection:selectedRowPath.section];
+    XLFormRowDescriptor * nextFormRow = [self.formViewController.form formRowAtIndex:nextRowPath];
+    XLFormSectionDescriptor * formSection = [self.formViewController.form.formSections objectAtIndex:nextRowPath.section];
+    BOOL result = [super resignFirstResponder];
+    if (result) {
+        [formSection removeFormRow:nextFormRow];
+    }
+    return result;
+}
+
+
+#pragma mark - XLFormDescriptorCell
+
+-(void)configure
+{
+    [super configure];
+}
+
+-(void)update
+{
+    [super update];
+    self.accessoryType = UITableViewCellAccessoryNone;
+    self.editingAccessoryType = UITableViewCellAccessoryNone;
+    [self.textLabel setText:self.rowDescriptor.title];
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    self.detailTextLabel.text = [self valueDisplayText];
+}
+
+-(BOOL)formDescriptorCellCanBecomeFirstResponder
+{
+    return !(self.rowDescriptor.isDisabled);
+}
+
+-(BOOL)formDescriptorCellBecomeFirstResponder
+{
+    
+    if ([self isFirstResponder]){
+        [self resignFirstResponder];
+        return NO;
+    }
+    return [self becomeFirstResponder];
+}
+
+-(void)formDescriptorCellDidSelectedWithFormController:(XLFormViewController *)controller
+{
+    [controller.tableView deselectRowAtIndexPath:[controller.form indexPathOfFormRow:self.rowDescriptor] animated:YES];
+}
+
+#pragma mark - Helpers
+
+-(NSString *)valueDisplayText
+{
+    return (self.rowDescriptor.value ? [self.rowDescriptor.value displayText] : self.rowDescriptor.noValueDisplayText);
+}
+
+
+
+@end
+
+
+
+
+@implementation XLFormInlineSegmentedControl
+
+@synthesize segmentedControl = _segmentedControl;
+@synthesize inlineRowDescriptor = _inlineRowDescriptor;
+
+
++(void)load
+{
+    [XLFormViewController.cellClassesForRowDescriptorTypes setObject:[XLFormInlineSegmentedControl class] forKey:XLFormRowDescriptorTypeSegmentedControl];
+}
+
+-(void)configure
+{
+    [super configure];
+    self.selectionStyle = UITableViewCellSelectionStyleNone;
+    [self.contentView addSubview:self.segmentedControl];
+    [self.contentView addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|-[segmentedControl]-|"
+                                                                           options:NSLayoutFormatAlignAllCenterY
+                                                                           metrics:0
+                                                                              views:@{@"segmentedControl": self.segmentedControl}]];
+    [self.segmentedControl addTarget:self action:@selector(valueChanged) forControlEvents:UIControlEventValueChanged];
+}
+
+-(void)update
+{
+    [super update];
+    [self updateSegmentedControl];
+    self.segmentedControl.selectedSegmentIndex = [self selectedIndex];
+    self.segmentedControl.enabled = !self.rowDescriptor.isDisabled;
+}
+
+-(UISegmentedControl *)segmentedControl
+{
+    if (_segmentedControl) return _segmentedControl;
+    
+    _segmentedControl = [UISegmentedControl autolayoutView];
+    [_segmentedControl setContentHuggingPriority:500 forAxis:UILayoutConstraintAxisHorizontal];
+    return _segmentedControl;
+}
+
+
+#pragma mark - Action
+
+-(void)valueChanged
+{
+    self.inlineRowDescriptor.value = [self.inlineRowDescriptor.selectorOptions objectAtIndex:self.segmentedControl.selectedSegmentIndex];
+    [self.formViewController updateFormRow:self.inlineRowDescriptor];
+}
+
+#pragma mark - Helper
+
+-(NSArray *)getItems
+{
+    NSMutableArray * result = [[NSMutableArray alloc] init];
+    for (id option in self.inlineRowDescriptor.selectorOptions)
+        [result addObject:[option displayText]];
+    return result;
+}
+
+-(void)updateSegmentedControl
+{
+    [self.segmentedControl removeAllSegments];
+    
+    [[self getItems] enumerateObjectsUsingBlock:^(id object, NSUInteger idex, __unused BOOL *stop){
+        [self.segmentedControl insertSegmentWithTitle:[object displayText] atIndex:idex animated:NO];
+    }];
+}
+
+-(NSInteger)selectedIndex
+{
+    XLFormRowDescriptor * formRow = self.inlineRowDescriptor ?: self.rowDescriptor;
+    if (formRow.value){
+        for (id option in formRow.selectorOptions){
+            if ([[option valueData] isEqual:[formRow.value valueData]]){
+                return [formRow.selectorOptions indexOfObject:option];
+            }
+        }
+    }
+    return -1;
+}
+
+@end

+ 17 - 0
Examples/Objective-C/Podfile

@@ -0,0 +1,17 @@
+source 'https://github.com/CocoaPods/Specs.git'
+platform :ios, '8.0'
+
+target 'XLForm' do
+
+
+
+#Following pods are used for custom row examples
+pod 'AFNetworking', '~> 2.0', :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
+pod 'SHSPhoneComponent'
+pod 'TZImagePickerController'
+pod 'XLForm'
+
+end

+ 836 - 0
Examples/Objective-C/XLForm.xcodeproj/project.pbxproj

@@ -0,0 +1,836 @@
+// !$*UTF8*$!
+{
+	archiveVersion = 1;
+	classes = {
+	};
+	objectVersion = 46;
+	objects = {
+
+/* Begin PBXBuildFile section */
+		06377AFA1F87F3AB003D0078 /* LxGridViewFlowLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 06377AF51F87F3AB003D0078 /* LxGridViewFlowLayout.m */; };
+		06377AFB1F87F3AB003D0078 /* TZPhotoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06377AF71F87F3AB003D0078 /* TZPhotoCell.m */; };
+		06377AFC1F87F3AB003D0078 /* TZTestCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06377AF91F87F3AB003D0078 /* TZTestCell.m */; };
+		06536E131F8870160066BC2F /* FYSectionCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 06536E111F8870160066BC2F /* FYSectionCell.m */; };
+		06536E141F8870160066BC2F /* FYSectionCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 06536E121F8870160066BC2F /* FYSectionCell.xib */; };
+		281E5BE919538F4A006D93C5 /* CLLocationValueTrasformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 281E5BE819538F4A006D93C5 /* CLLocationValueTrasformer.m */; };
+		282EB27C1AB5FF33004A736F /* AccessoryViewFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 282EB27B1AB5FF33004A736F /* AccessoryViewFormViewController.m */; };
+		283B59B219532415000828CD /* MapViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 283B59B119532415000828CD /* MapViewController.m */; };
+		283B59B7195334AF000828CD /* CustomSelectorsFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 283B59B6195334AF000828CD /* CustomSelectorsFormViewController.m */; };
+		283C6B7D1999BAF100A5283D /* UICustomizationFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 283C6B7C1999BAF100A5283D /* UICustomizationFormViewController.m */; };
+		2843EB4718D4915800F13E2B /* ExamplesFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2843EB4618D4915800F13E2B /* ExamplesFormViewController.m */; };
+		2843EB4B18D496F600F13E2B /* SelectorsFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2843EB4A18D496F600F13E2B /* SelectorsFormViewController.m */; };
+		2843EB5218D4CFC700F13E2B /* OthersFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2843EB5118D4CFC700F13E2B /* OthersFormViewController.m */; };
+		2843EB5618D4F7B700F13E2B /* DatesFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 2843EB5518D4F7B700F13E2B /* DatesFormViewController.m */; };
+		28468E9818EC686500DBB015 /* NativeEventFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28468E9718EC686500DBB015 /* NativeEventFormViewController.m */; };
+		28468EA418EF41D300DBB015 /* InputsFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28468EA318EF41D300DBB015 /* InputsFormViewController.m */; };
+		28468EA718EF594900DBB015 /* Localizable.strings in Resources */ = {isa = PBXBuildFile; fileRef = 28468EA518EF594800DBB015 /* Localizable.strings */; };
+		2850C5FC18D0F706002B7D0A /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2850C5FB18D0F706002B7D0A /* Foundation.framework */; };
+		2850C5FE18D0F706002B7D0A /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2850C5FD18D0F706002B7D0A /* CoreGraphics.framework */; };
+		2850C60018D0F706002B7D0A /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2850C5FF18D0F706002B7D0A /* UIKit.framework */; };
+		2850C60618D0F706002B7D0A /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 2850C60418D0F706002B7D0A /* InfoPlist.strings */; };
+		2850C60818D0F706002B7D0A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 2850C60718D0F706002B7D0A /* main.m */; };
+		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 */; };
+		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 */; };
+		28A85D5918E346C100E81A26 /* XLFormImageSelectorCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 28A85D5818E346C100E81A26 /* XLFormImageSelectorCell.m */; };
+		28DBB04118D76FDC00FB8A8B /* MultivaluedFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28DBB04018D76FDC00FB8A8B /* MultivaluedFormViewController.m */; };
+		28F89F2E1AA4EA5600E90218 /* ValidationExamplesFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 28F89F2D1AA4EA5600E90218 /* ValidationExamplesFormViewController.m */; };
+		3C0357F01AB0D82300200C8A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 3C0357EF1AB0D82300200C8A /* Images.xcassets */; };
+		3C3B01D51AB741EF0027CD45 /* XLFormRatingCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01D31AB741EF0027CD45 /* XLFormRatingCell.m */; };
+		3C3B01DA1AB7497D0027CD45 /* XLFormWeekDaysCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01D81AB7497D0027CD45 /* XLFormWeekDaysCell.m */; };
+		3C3B01DB1AB7497D0027CD45 /* XLFormWeekDaysCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3C3B01D91AB7497D0027CD45 /* XLFormWeekDaysCell.xib */; };
+		3C3B01E21AB7499A0027CD45 /* XLRatingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01E01AB7499A0027CD45 /* XLRatingView.m */; };
+		3C3B01F01AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C3B01EF1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m */; };
+		3CDAFC7A1AB0AFA4000F75B6 /* CustomRowsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 3CDAFC791AB0AFA4000F75B6 /* CustomRowsViewController.m */; };
+		5BB6B032D80344C9E7D956CD /* libPods-XLForm.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 19383D268EF8024CB33FCCA4 /* libPods-XLForm.a */; };
+		66B6266E1AE0055100007886 /* DateAndTimeValueTrasformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */; };
+		BF01E9281C21F0BB00BDE045 /* XLFormInlineSegmentedCell.m in Sources */ = {isa = PBXBuildFile; fileRef = BF01E9271C21F0BB00BDE045 /* XLFormInlineSegmentedCell.m */; };
+		BF9DB1D51AE0436600B985E7 /* BlogExampleViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */; };
+		BF9DB1D61AE0436600B985E7 /* PredicateFormViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */; };
+		BFA5F4B11BB48F8E00D045BD /* XLFormRatingCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3C3B01D41AB741EF0027CD45 /* XLFormRatingCell.xib */; };
+		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 */; };
+		DEB8235C1AD5529A00AF9FE2 /* FormattersViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXFileReference section */
+		06377AF41F87F3AB003D0078 /* LxGridViewFlowLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LxGridViewFlowLayout.h; sourceTree = "<group>"; };
+		06377AF51F87F3AB003D0078 /* LxGridViewFlowLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LxGridViewFlowLayout.m; sourceTree = "<group>"; };
+		06377AF61F87F3AB003D0078 /* TZPhotoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZPhotoCell.h; sourceTree = "<group>"; };
+		06377AF71F87F3AB003D0078 /* TZPhotoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZPhotoCell.m; sourceTree = "<group>"; };
+		06377AF81F87F3AB003D0078 /* TZTestCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TZTestCell.h; sourceTree = "<group>"; };
+		06377AF91F87F3AB003D0078 /* TZTestCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TZTestCell.m; sourceTree = "<group>"; };
+		06536E101F8870160066BC2F /* FYSectionCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FYSectionCell.h; sourceTree = "<group>"; };
+		06536E111F8870160066BC2F /* FYSectionCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FYSectionCell.m; sourceTree = "<group>"; };
+		06536E121F8870160066BC2F /* FYSectionCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = FYSectionCell.xib; sourceTree = "<group>"; };
+		19383D268EF8024CB33FCCA4 /* libPods-XLForm.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-XLForm.a"; sourceTree = BUILT_PRODUCTS_DIR; };
+		281E5BE719538F4A006D93C5 /* CLLocationValueTrasformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CLLocationValueTrasformer.h; path = Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.h; sourceTree = "<group>"; };
+		281E5BE819538F4A006D93C5 /* CLLocationValueTrasformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CLLocationValueTrasformer.m; path = Examples/Selectors/CustomSelectors/XLFormRowViewController/CLLocationValueTrasformer.m; sourceTree = "<group>"; };
+		282EB27A1AB5FF33004A736F /* AccessoryViewFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = AccessoryViewFormViewController.h; path = Examples/AccessoryViews/AccessoryViewFormViewController.h; sourceTree = "<group>"; };
+		282EB27B1AB5FF33004A736F /* AccessoryViewFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = AccessoryViewFormViewController.m; path = Examples/AccessoryViews/AccessoryViewFormViewController.m; sourceTree = "<group>"; };
+		283B59B019532415000828CD /* MapViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MapViewController.h; path = Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.h; sourceTree = "<group>"; };
+		283B59B119532415000828CD /* MapViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MapViewController.m; path = Examples/Selectors/CustomSelectors/XLFormRowViewController/MapViewController.m; sourceTree = "<group>"; };
+		283B59B5195334AF000828CD /* CustomSelectorsFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomSelectorsFormViewController.h; path = Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.h; sourceTree = "<group>"; };
+		283B59B6195334AF000828CD /* CustomSelectorsFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CustomSelectorsFormViewController.m; path = Examples/Selectors/CustomSelectors/CustomSelectorsFormViewController.m; sourceTree = "<group>"; };
+		283C6B7B1999BAF100A5283D /* UICustomizationFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = UICustomizationFormViewController.h; path = Examples/UICustomization/UICustomizationFormViewController.h; sourceTree = "<group>"; };
+		283C6B7C1999BAF100A5283D /* UICustomizationFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = UICustomizationFormViewController.m; path = Examples/UICustomization/UICustomizationFormViewController.m; sourceTree = "<group>"; };
+		2843EB4518D4915800F13E2B /* ExamplesFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = ExamplesFormViewController.h; path = Examples/ExamplesFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		2843EB4618D4915800F13E2B /* ExamplesFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = ExamplesFormViewController.m; path = Examples/ExamplesFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		2843EB4918D496F600F13E2B /* SelectorsFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = SelectorsFormViewController.h; path = Examples/Selectors/SelectorsFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		2843EB4A18D496F600F13E2B /* SelectorsFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = SelectorsFormViewController.m; path = Examples/Selectors/SelectorsFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		2843EB5018D4CFC700F13E2B /* OthersFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = OthersFormViewController.h; path = Examples/Others/OthersFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		2843EB5118D4CFC700F13E2B /* OthersFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = OthersFormViewController.m; path = Examples/Others/OthersFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		2843EB5418D4F7B700F13E2B /* DatesFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = DatesFormViewController.h; path = Examples/Dates/DatesFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		2843EB5518D4F7B700F13E2B /* DatesFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = DatesFormViewController.m; path = Examples/Dates/DatesFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		28468E9618EC686500DBB015 /* NativeEventFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = NativeEventFormViewController.h; path = Examples/RealExamples/NativeEventFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		28468E9718EC686500DBB015 /* NativeEventFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = NativeEventFormViewController.m; path = Examples/RealExamples/NativeEventFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		28468EA218EF41D300DBB015 /* InputsFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = InputsFormViewController.h; path = Examples/Inputs/InputsFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		28468EA318EF41D300DBB015 /* InputsFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = InputsFormViewController.m; path = Examples/Inputs/InputsFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		28468EA618EF594800DBB015 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/Localizable.strings; sourceTree = "<group>"; };
+		2850C5F818D0F706002B7D0A /* XLForm.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XLForm.app; sourceTree = BUILT_PRODUCTS_DIR; };
+		2850C5FB18D0F706002B7D0A /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+		2850C5FD18D0F706002B7D0A /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+		2850C5FF18D0F706002B7D0A /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+		2850C60318D0F706002B7D0A /* XLForm-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "XLForm-Info.plist"; sourceTree = "<group>"; };
+		2850C60518D0F706002B7D0A /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
+		2850C60718D0F706002B7D0A /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = main.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		2850C60918D0F706002B7D0A /* XLForm-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "XLForm-Prefix.pch"; sourceTree = "<group>"; };
+		2850C60A18D0F706002B7D0A /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = AppDelegate.h; path = Examples/AppDelegate.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		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>"; };
+		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>"; };
+		28A7665D1932F61100D69546 /* DynamicSelectorsFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DynamicSelectorsFormViewController.m; path = Examples/Selectors/DynamicSelector/DynamicSelectorsFormViewController.m; sourceTree = "<group>"; };
+		28A8083D190D9083009D77F8 /* iPhoneStoryboard.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = iPhoneStoryboard.storyboard; path = Examples/StoryboardExample/iPhoneStoryboard.storyboard; sourceTree = "<group>"; };
+		28A85D5718E346C100E81A26 /* XLFormImageSelectorCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = XLFormImageSelectorCell.h; path = Examples/Others/CustomCells/XLFormImageSelectorCell.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		28A85D5818E346C100E81A26 /* XLFormImageSelectorCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = XLFormImageSelectorCell.m; path = Examples/Others/CustomCells/XLFormImageSelectorCell.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		28DBB03F18D76FDC00FB8A8B /* MultivaluedFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; lineEnding = 0; name = MultivaluedFormViewController.h; path = Examples/MultiValuedSections/MultivaluedFormViewController.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
+		28DBB04018D76FDC00FB8A8B /* MultivaluedFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = MultivaluedFormViewController.m; path = Examples/MultiValuedSections/MultivaluedFormViewController.m; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
+		28F89F2C1AA4EA5600E90218 /* ValidationExamplesFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ValidationExamplesFormViewController.h; path = Examples/Validations/ValidationExamplesFormViewController.h; sourceTree = "<group>"; };
+		28F89F2D1AA4EA5600E90218 /* ValidationExamplesFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = ValidationExamplesFormViewController.m; path = Examples/Validations/ValidationExamplesFormViewController.m; sourceTree = "<group>"; };
+		3C0357EF1AB0D82300200C8A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
+		3C3B01D21AB741EF0027CD45 /* XLFormRatingCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLFormRatingCell.h; path = Examples/CustomRows/Rating/XLFormRatingCell.h; sourceTree = "<group>"; };
+		3C3B01D31AB741EF0027CD45 /* XLFormRatingCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormRatingCell.m; path = Examples/CustomRows/Rating/XLFormRatingCell.m; sourceTree = "<group>"; };
+		3C3B01D41AB741EF0027CD45 /* XLFormRatingCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = XLFormRatingCell.xib; path = Examples/CustomRows/Rating/XLFormRatingCell.xib; sourceTree = "<group>"; };
+		3C3B01D71AB7497D0027CD45 /* XLFormWeekDaysCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLFormWeekDaysCell.h; path = Examples/CustomRows/Weekdays/XLFormWeekDaysCell.h; sourceTree = "<group>"; };
+		3C3B01D81AB7497D0027CD45 /* XLFormWeekDaysCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormWeekDaysCell.m; path = Examples/CustomRows/Weekdays/XLFormWeekDaysCell.m; sourceTree = "<group>"; };
+		3C3B01D91AB7497D0027CD45 /* XLFormWeekDaysCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = XLFormWeekDaysCell.xib; path = Examples/CustomRows/Weekdays/XLFormWeekDaysCell.xib; sourceTree = "<group>"; };
+		3C3B01DE1AB7499A0027CD45 /* XLRatingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLRatingView.h; path = Examples/CustomRows/Rating/RatingView/XLRatingView.h; sourceTree = "<group>"; };
+		3C3B01E01AB7499A0027CD45 /* XLRatingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLRatingView.m; path = Examples/CustomRows/Rating/RatingView/XLRatingView.m; sourceTree = "<group>"; };
+		3C3B01EE1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FloatLabeledTextFieldCell.h; path = Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.h; sourceTree = "<group>"; };
+		3C3B01EF1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = FloatLabeledTextFieldCell.m; path = Examples/CustomRows/FloatLabeledTextField/FloatLabeledTextFieldCell.m; sourceTree = "<group>"; };
+		3CDAFC781AB0AFA4000F75B6 /* CustomRowsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = CustomRowsViewController.h; path = Examples/CustomRows/CustomRowsViewController.h; sourceTree = "<group>"; };
+		3CDAFC791AB0AFA4000F75B6 /* CustomRowsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = CustomRowsViewController.m; path = Examples/CustomRows/CustomRowsViewController.m; sourceTree = "<group>"; };
+		5F6FC67A75254B60005DC716 /* Pods-XLForm.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XLForm.debug.xcconfig"; path = "Pods/Target Support Files/Pods-XLForm/Pods-XLForm.debug.xcconfig"; sourceTree = "<group>"; };
+		66B6266C1AE0055100007886 /* DateAndTimeValueTrasformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DateAndTimeValueTrasformer.h; path = Examples/Dates/DateAndTimeValueTrasformer.h; sourceTree = "<group>"; };
+		66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = DateAndTimeValueTrasformer.m; path = Examples/Dates/DateAndTimeValueTrasformer.m; sourceTree = "<group>"; };
+		B98C1213E7C714A861219C81 /* Pods-XLForm.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-XLForm.release.xcconfig"; path = "Pods/Target Support Files/Pods-XLForm/Pods-XLForm.release.xcconfig"; sourceTree = "<group>"; };
+		BF01E9261C21F0BB00BDE045 /* XLFormInlineSegmentedCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLFormInlineSegmentedCell.h; path = "Inline Segmented/XLFormInlineSegmentedCell.h"; sourceTree = "<group>"; };
+		BF01E9271C21F0BB00BDE045 /* XLFormInlineSegmentedCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormInlineSegmentedCell.m; path = "Inline Segmented/XLFormInlineSegmentedCell.m"; sourceTree = "<group>"; };
+		BF9DB1D11AE0436600B985E7 /* BlogExampleViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BlogExampleViewController.h; path = Examples/PredicateExamples/BlogExampleViewController.h; sourceTree = SOURCE_ROOT; };
+		BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BlogExampleViewController.m; path = Examples/PredicateExamples/BlogExampleViewController.m; sourceTree = SOURCE_ROOT; };
+		BF9DB1D31AE0436600B985E7 /* PredicateFormViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PredicateFormViewController.h; path = Examples/PredicateExamples/PredicateFormViewController.h; sourceTree = SOURCE_ROOT; };
+		BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PredicateFormViewController.m; path = Examples/PredicateExamples/PredicateFormViewController.m; sourceTree = SOURCE_ROOT; };
+		BFE91AF91AE159B200DE5231 /* BasicPredicateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = BasicPredicateViewController.h; path = Examples/PredicateExamples/BasicPredicateViewController.h; sourceTree = SOURCE_ROOT; };
+		BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = BasicPredicateViewController.m; path = Examples/PredicateExamples/BasicPredicateViewController.m; sourceTree = SOURCE_ROOT; };
+		D51B8B2A19126664008C0478 /* XLFormCustomCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = XLFormCustomCell.h; path = Examples/Others/CustomCells/XLFormCustomCell.h; sourceTree = "<group>"; };
+		D51B8B2B19126664008C0478 /* XLFormCustomCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = XLFormCustomCell.m; path = Examples/Others/CustomCells/XLFormCustomCell.m; sourceTree = "<group>"; };
+		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>"; };
+		DEB8235A1AD5529A00AF9FE2 /* FormattersViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FormattersViewController.h; sourceTree = "<group>"; };
+		DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FormattersViewController.m; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+		2850C5F518D0F706002B7D0A /* Frameworks */ = {
+			isa = PBXFrameworksBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				28A7661F193248BD00D69546 /* CoreData.framework in Frameworks */,
+				2850C5FE18D0F706002B7D0A /* CoreGraphics.framework in Frameworks */,
+				2850C60018D0F706002B7D0A /* UIKit.framework in Frameworks */,
+				2850C5FC18D0F706002B7D0A /* Foundation.framework in Frameworks */,
+				5BB6B032D80344C9E7D956CD /* libPods-XLForm.a in Frameworks */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+		06377AF31F87F3AB003D0078 /* TZImagePicker */ = {
+			isa = PBXGroup;
+			children = (
+				06377AF41F87F3AB003D0078 /* LxGridViewFlowLayout.h */,
+				06377AF51F87F3AB003D0078 /* LxGridViewFlowLayout.m */,
+				06377AF61F87F3AB003D0078 /* TZPhotoCell.h */,
+				06377AF71F87F3AB003D0078 /* TZPhotoCell.m */,
+				06377AF81F87F3AB003D0078 /* TZTestCell.h */,
+				06377AF91F87F3AB003D0078 /* TZTestCell.m */,
+			);
+			name = TZImagePicker;
+			path = Examples/CustomRows/TZImagePicker;
+			sourceTree = "<group>";
+		};
+		06536E0F1F886FE70066BC2F /* Section */ = {
+			isa = PBXGroup;
+			children = (
+				06536E101F8870160066BC2F /* FYSectionCell.h */,
+				06536E111F8870160066BC2F /* FYSectionCell.m */,
+				06536E121F8870160066BC2F /* FYSectionCell.xib */,
+			);
+			name = Section;
+			path = Examples/CustomRows/Section;
+			sourceTree = "<group>";
+		};
+		282C5EEF18D33C1800A5D47C /* Inputs */ = {
+			isa = PBXGroup;
+			children = (
+				28468EA218EF41D300DBB015 /* InputsFormViewController.h */,
+				28468EA318EF41D300DBB015 /* InputsFormViewController.m */,
+			);
+			name = Inputs;
+			sourceTree = "<group>";
+		};
+		282EB2791AB5FD66004A736F /* AccessoryViews */ = {
+			isa = PBXGroup;
+			children = (
+				282EB27A1AB5FF33004A736F /* AccessoryViewFormViewController.h */,
+				282EB27B1AB5FF33004A736F /* AccessoryViewFormViewController.m */,
+			);
+			name = AccessoryViews;
+			sourceTree = "<group>";
+		};
+		283B59AF19531DDA000828CD /* CustomSelectors */ = {
+			isa = PBXGroup;
+			children = (
+				283B59B319532A8E000828CD /* XLFormRowViewController */,
+				283B59B5195334AF000828CD /* CustomSelectorsFormViewController.h */,
+				283B59B6195334AF000828CD /* CustomSelectorsFormViewController.m */,
+			);
+			name = CustomSelectors;
+			sourceTree = "<group>";
+		};
+		283B59B319532A8E000828CD /* XLFormRowViewController */ = {
+			isa = PBXGroup;
+			children = (
+				283B59B019532415000828CD /* MapViewController.h */,
+				283B59B119532415000828CD /* MapViewController.m */,
+				281E5BE719538F4A006D93C5 /* CLLocationValueTrasformer.h */,
+				281E5BE819538F4A006D93C5 /* CLLocationValueTrasformer.m */,
+				28815E2D1A8589F600B674D2 /* MapViewController.xib */,
+			);
+			name = XLFormRowViewController;
+			sourceTree = "<group>";
+		};
+		283C6B7A1999BA1B00A5283D /* UICustomization */ = {
+			isa = PBXGroup;
+			children = (
+				283C6B7B1999BAF100A5283D /* UICustomizationFormViewController.h */,
+				283C6B7C1999BAF100A5283D /* UICustomizationFormViewController.m */,
+			);
+			name = UICustomization;
+			sourceTree = "<group>";
+		};
+		2843EB4818D496CB00F13E2B /* Selectors */ = {
+			isa = PBXGroup;
+			children = (
+				283B59AF19531DDA000828CD /* CustomSelectors */,
+				28A766521932F1FA00D69546 /* DynamicSelector */,
+				2843EB4918D496F600F13E2B /* SelectorsFormViewController.h */,
+				2843EB4A18D496F600F13E2B /* SelectorsFormViewController.m */,
+			);
+			name = Selectors;
+			sourceTree = "<group>";
+		};
+		2843EB4F18D4CFA100F13E2B /* Others */ = {
+			isa = PBXGroup;
+			children = (
+				28A7662A1932A3D800D69546 /* CustomCells */,
+				2843EB5018D4CFC700F13E2B /* OthersFormViewController.h */,
+				2843EB5118D4CFC700F13E2B /* OthersFormViewController.m */,
+			);
+			name = Others;
+			sourceTree = "<group>";
+		};
+		2843EB5318D4F77F00F13E2B /* Dates */ = {
+			isa = PBXGroup;
+			children = (
+				66B6266C1AE0055100007886 /* DateAndTimeValueTrasformer.h */,
+				66B6266D1AE0055100007886 /* DateAndTimeValueTrasformer.m */,
+				2843EB5418D4F7B700F13E2B /* DatesFormViewController.h */,
+				2843EB5518D4F7B700F13E2B /* DatesFormViewController.m */,
+			);
+			name = Dates;
+			sourceTree = "<group>";
+		};
+		2843EB5F18D76B2D00F13E2B /* MultiValuedSections */ = {
+			isa = PBXGroup;
+			children = (
+				28DBB03F18D76FDC00FB8A8B /* MultivaluedFormViewController.h */,
+				28DBB04018D76FDC00FB8A8B /* MultivaluedFormViewController.m */,
+			);
+			name = MultiValuedSections;
+			sourceTree = "<group>";
+		};
+		28468E9218EA52CA00DBB015 /* RealExamples */ = {
+			isa = PBXGroup;
+			children = (
+				28468E9618EC686500DBB015 /* NativeEventFormViewController.h */,
+				28468E9718EC686500DBB015 /* NativeEventFormViewController.m */,
+			);
+			name = RealExamples;
+			sourceTree = "<group>";
+		};
+		2850C5EF18D0F706002B7D0A = {
+			isa = PBXGroup;
+			children = (
+				2850C62B18D0F92F002B7D0A /* Examples */,
+				2850C60118D0F706002B7D0A /* XLForm */,
+				2850C5FA18D0F706002B7D0A /* Frameworks */,
+				2850C5F918D0F706002B7D0A /* Products */,
+				B6478577DDCB0DDDD433C572 /* Pods */,
+			);
+			sourceTree = "<group>";
+		};
+		2850C5F918D0F706002B7D0A /* Products */ = {
+			isa = PBXGroup;
+			children = (
+				2850C5F818D0F706002B7D0A /* XLForm.app */,
+			);
+			name = Products;
+			sourceTree = "<group>";
+		};
+		2850C5FA18D0F706002B7D0A /* Frameworks */ = {
+			isa = PBXGroup;
+			children = (
+				28A7661E193248BD00D69546 /* CoreData.framework */,
+				2850C5FB18D0F706002B7D0A /* Foundation.framework */,
+				2850C5FD18D0F706002B7D0A /* CoreGraphics.framework */,
+				2850C5FF18D0F706002B7D0A /* UIKit.framework */,
+				19383D268EF8024CB33FCCA4 /* libPods-XLForm.a */,
+			);
+			name = Frameworks;
+			sourceTree = "<group>";
+		};
+		2850C60118D0F706002B7D0A /* XLForm */ = {
+			isa = PBXGroup;
+			children = (
+				2850C60218D0F706002B7D0A /* Supporting Files */,
+			);
+			path = XLForm;
+			sourceTree = "<group>";
+		};
+		2850C60218D0F706002B7D0A /* Supporting Files */ = {
+			isa = PBXGroup;
+			children = (
+				3C0357EF1AB0D82300200C8A /* Images.xcassets */,
+				2850C60318D0F706002B7D0A /* XLForm-Info.plist */,
+				2850C60418D0F706002B7D0A /* InfoPlist.strings */,
+				2850C60718D0F706002B7D0A /* main.m */,
+				2850C60918D0F706002B7D0A /* XLForm-Prefix.pch */,
+				28468EA518EF594800DBB015 /* Localizable.strings */,
+			);
+			name = "Supporting Files";
+			sourceTree = "<group>";
+		};
+		2850C62B18D0F92F002B7D0A /* Examples */ = {
+			isa = PBXGroup;
+			children = (
+				282EB2791AB5FD66004A736F /* AccessoryViews */,
+				3CDAFC741AB0AEE5000F75B6 /* CustomRows */,
+				28F89F2B1AA4E99500E90218 /* Validations */,
+				DEB823591AD5529A00AF9FE2 /* Formatters */,
+				283C6B7A1999BA1B00A5283D /* UICustomization */,
+				28A76624193251E500D69546 /* AppDelegate.m */,
+				28A8083C190D903D009D77F8 /* StoryboardExample */,
+				28468E9218EA52CA00DBB015 /* RealExamples */,
+				2843EB5F18D76B2D00F13E2B /* MultiValuedSections */,
+				2843EB5318D4F77F00F13E2B /* Dates */,
+				2843EB4F18D4CFA100F13E2B /* Others */,
+				2843EB4818D496CB00F13E2B /* Selectors */,
+				2850C60A18D0F706002B7D0A /* AppDelegate.h */,
+				BFD5D6F41AD2FFC1006F04FA /* PredicateExamples */,
+				282C5EEF18D33C1800A5D47C /* Inputs */,
+				2843EB4518D4915800F13E2B /* ExamplesFormViewController.h */,
+				2843EB4618D4915800F13E2B /* ExamplesFormViewController.m */,
+			);
+			name = Examples;
+			sourceTree = "<group>";
+		};
+		28A7662A1932A3D800D69546 /* CustomCells */ = {
+			isa = PBXGroup;
+			children = (
+				28A85D5718E346C100E81A26 /* XLFormImageSelectorCell.h */,
+				28A85D5818E346C100E81A26 /* XLFormImageSelectorCell.m */,
+				D51B8B2A19126664008C0478 /* XLFormCustomCell.h */,
+				D51B8B2B19126664008C0478 /* XLFormCustomCell.m */,
+			);
+			name = CustomCells;
+			sourceTree = "<group>";
+		};
+		28A766521932F1FA00D69546 /* DynamicSelector */ = {
+			isa = PBXGroup;
+			children = (
+				DEA6EF8E1B57D698000F4893 /* SessionManager */,
+				28A7665A1932F55700D69546 /* XLFormRowViewController */,
+				28A7665C1932F61100D69546 /* DynamicSelectorsFormViewController.h */,
+				28A7665D1932F61100D69546 /* DynamicSelectorsFormViewController.m */,
+			);
+			name = DynamicSelector;
+			sourceTree = "<group>";
+		};
+		28A7665A1932F55700D69546 /* XLFormRowViewController */ = {
+			isa = PBXGroup;
+			children = (
+				28A766531932F22400D69546 /* UsersTableViewController.h */,
+				28A766541932F22400D69546 /* UsersTableViewController.m */,
+			);
+			name = XLFormRowViewController;
+			sourceTree = "<group>";
+		};
+		28A8083C190D903D009D77F8 /* StoryboardExample */ = {
+			isa = PBXGroup;
+			children = (
+				28A8083D190D9083009D77F8 /* iPhoneStoryboard.storyboard */,
+			);
+			name = StoryboardExample;
+			sourceTree = "<group>";
+		};
+		28F89F2B1AA4E99500E90218 /* Validations */ = {
+			isa = PBXGroup;
+			children = (
+				28F89F2C1AA4EA5600E90218 /* ValidationExamplesFormViewController.h */,
+				28F89F2D1AA4EA5600E90218 /* ValidationExamplesFormViewController.m */,
+			);
+			name = Validations;
+			sourceTree = "<group>";
+		};
+		3C3B01D01AB741C40027CD45 /* Rating */ = {
+			isa = PBXGroup;
+			children = (
+				3C3B01DC1AB7498B0027CD45 /* RatingView */,
+				3C3B01D21AB741EF0027CD45 /* XLFormRatingCell.h */,
+				3C3B01D31AB741EF0027CD45 /* XLFormRatingCell.m */,
+				3C3B01D41AB741EF0027CD45 /* XLFormRatingCell.xib */,
+			);
+			name = Rating;
+			sourceTree = "<group>";
+		};
+		3C3B01D11AB741CC0027CD45 /* Weekdays */ = {
+			isa = PBXGroup;
+			children = (
+				3C3B01D71AB7497D0027CD45 /* XLFormWeekDaysCell.h */,
+				3C3B01D81AB7497D0027CD45 /* XLFormWeekDaysCell.m */,
+				3C3B01D91AB7497D0027CD45 /* XLFormWeekDaysCell.xib */,
+			);
+			name = Weekdays;
+			sourceTree = "<group>";
+		};
+		3C3B01DC1AB7498B0027CD45 /* RatingView */ = {
+			isa = PBXGroup;
+			children = (
+				3C3B01DE1AB7499A0027CD45 /* XLRatingView.h */,
+				3C3B01E01AB7499A0027CD45 /* XLRatingView.m */,
+			);
+			name = RatingView;
+			sourceTree = "<group>";
+		};
+		3C3B01E31AB74AC10027CD45 /* FloatLabeledTextField */ = {
+			isa = PBXGroup;
+			children = (
+				3C3B01EE1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.h */,
+				3C3B01EF1AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m */,
+			);
+			name = FloatLabeledTextField;
+			sourceTree = "<group>";
+		};
+		3CDAFC741AB0AEE5000F75B6 /* CustomRows */ = {
+			isa = PBXGroup;
+			children = (
+				BF01E9251C21F02D00BDE045 /* Inline Segmented */,
+				3C3B01D01AB741C40027CD45 /* Rating */,
+				3C3B01E31AB74AC10027CD45 /* FloatLabeledTextField */,
+				3C3B01D11AB741CC0027CD45 /* Weekdays */,
+				06377AF31F87F3AB003D0078 /* TZImagePicker */,
+				06536E0F1F886FE70066BC2F /* Section */,
+				3CDAFC781AB0AFA4000F75B6 /* CustomRowsViewController.h */,
+				3CDAFC791AB0AFA4000F75B6 /* CustomRowsViewController.m */,
+			);
+			name = CustomRows;
+			sourceTree = "<group>";
+		};
+		B6478577DDCB0DDDD433C572 /* Pods */ = {
+			isa = PBXGroup;
+			children = (
+				5F6FC67A75254B60005DC716 /* Pods-XLForm.debug.xcconfig */,
+				B98C1213E7C714A861219C81 /* Pods-XLForm.release.xcconfig */,
+			);
+			name = Pods;
+			sourceTree = "<group>";
+		};
+		BF01E9251C21F02D00BDE045 /* Inline Segmented */ = {
+			isa = PBXGroup;
+			children = (
+				BF01E9261C21F0BB00BDE045 /* XLFormInlineSegmentedCell.h */,
+				BF01E9271C21F0BB00BDE045 /* XLFormInlineSegmentedCell.m */,
+			);
+			name = "Inline Segmented";
+			sourceTree = "<group>";
+		};
+		BFD5D6F41AD2FFC1006F04FA /* PredicateExamples */ = {
+			isa = PBXGroup;
+			children = (
+				BF9DB1D11AE0436600B985E7 /* BlogExampleViewController.h */,
+				BF9DB1D21AE0436600B985E7 /* BlogExampleViewController.m */,
+				BF9DB1D31AE0436600B985E7 /* PredicateFormViewController.h */,
+				BF9DB1D41AE0436600B985E7 /* PredicateFormViewController.m */,
+				BFE91AF91AE159B200DE5231 /* BasicPredicateViewController.h */,
+				BFE91AFA1AE159B200DE5231 /* BasicPredicateViewController.m */,
+			);
+			name = PredicateExamples;
+			path = Examples/PredicateDisabling;
+			sourceTree = "<group>";
+		};
+		DEA6EF8E1B57D698000F4893 /* SessionManager */ = {
+			isa = PBXGroup;
+			children = (
+				DEA6EF8F1B57D6CC000F4893 /* HTTPSessionManager.h */,
+				DEA6EF901B57D6CC000F4893 /* HTTPSessionManager.m */,
+			);
+			name = SessionManager;
+			sourceTree = "<group>";
+		};
+		DEB823591AD5529A00AF9FE2 /* Formatters */ = {
+			isa = PBXGroup;
+			children = (
+				DEB8235A1AD5529A00AF9FE2 /* FormattersViewController.h */,
+				DEB8235B1AD5529A00AF9FE2 /* FormattersViewController.m */,
+			);
+			name = Formatters;
+			path = Examples/Formatters;
+			sourceTree = "<group>";
+		};
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+		2850C5F718D0F706002B7D0A /* XLForm */ = {
+			isa = PBXNativeTarget;
+			buildConfigurationList = 2850C62418D0F707002B7D0A /* Build configuration list for PBXNativeTarget "XLForm" */;
+			buildPhases = (
+				EBE0335CCC7588D83B89A92A /* [CP] Check Pods Manifest.lock */,
+				2850C5F418D0F706002B7D0A /* Sources */,
+				2850C5F518D0F706002B7D0A /* Frameworks */,
+				2850C5F618D0F706002B7D0A /* Resources */,
+				32EB30E0A90A4E91864B1D3C /* [CP] Embed Pods Frameworks */,
+				DE3D12F5596780A66C6C3D4A /* [CP] Copy Pods Resources */,
+			);
+			buildRules = (
+			);
+			dependencies = (
+			);
+			name = XLForm;
+			productName = XLForm;
+			productReference = 2850C5F818D0F706002B7D0A /* XLForm.app */;
+			productType = "com.apple.product-type.application";
+		};
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+		2850C5F018D0F706002B7D0A /* Project object */ = {
+			isa = PBXProject;
+			attributes = {
+				LastUpgradeCheck = 0700;
+				ORGANIZATIONNAME = Xmartlabs;
+			};
+			buildConfigurationList = 2850C5F318D0F706002B7D0A /* Build configuration list for PBXProject "XLForm" */;
+			compatibilityVersion = "Xcode 3.2";
+			developmentRegion = English;
+			hasScannedForEncodings = 0;
+			knownRegions = (
+				en,
+			);
+			mainGroup = 2850C5EF18D0F706002B7D0A;
+			productRefGroup = 2850C5F918D0F706002B7D0A /* Products */;
+			projectDirPath = "";
+			projectRoot = "";
+			targets = (
+				2850C5F718D0F706002B7D0A /* XLForm */,
+			);
+		};
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+		2850C5F618D0F706002B7D0A /* Resources */ = {
+			isa = PBXResourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				28468EA718EF594900DBB015 /* Localizable.strings in Resources */,
+				2850C60618D0F706002B7D0A /* InfoPlist.strings in Resources */,
+				BFA5F4B11BB48F8E00D045BD /* XLFormRatingCell.xib in Resources */,
+				28815E2E1A8589F600B674D2 /* MapViewController.xib in Resources */,
+				3C0357F01AB0D82300200C8A /* Images.xcassets in Resources */,
+				3C3B01DB1AB7497D0027CD45 /* XLFormWeekDaysCell.xib in Resources */,
+				06536E141F8870160066BC2F /* FYSectionCell.xib in Resources */,
+				28A8083E190D9083009D77F8 /* iPhoneStoryboard.storyboard in Resources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+		32EB30E0A90A4E91864B1D3C /* [CP] Embed Pods Frameworks */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+			);
+			name = "[CP] Embed Pods Frameworks";
+			outputPaths = (
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XLForm/Pods-XLForm-frameworks.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		DE3D12F5596780A66C6C3D4A /* [CP] Copy Pods Resources */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"${SRCROOT}/Pods/Target Support Files/Pods-XLForm/Pods-XLForm-resources.sh",
+				"${PODS_ROOT}/TZImagePickerController/TZImagePickerController/TZImagePickerController/TZImagePickerController.bundle",
+				"${PODS_ROOT}/XLForm/XLForm/XLForm.bundle",
+			);
+			name = "[CP] Copy Pods Resources";
+			outputPaths = (
+				"${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-XLForm/Pods-XLForm-resources.sh\"\n";
+			showEnvVarsInLog = 0;
+		};
+		EBE0335CCC7588D83B89A92A /* [CP] Check Pods Manifest.lock */ = {
+			isa = PBXShellScriptBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+			);
+			inputPaths = (
+				"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
+				"${PODS_ROOT}/Manifest.lock",
+			);
+			name = "[CP] Check Pods Manifest.lock";
+			outputPaths = (
+				"$(DERIVED_FILE_DIR)/Pods-XLForm-checkManifestLockResult.txt",
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+			shellPath = /bin/sh;
+			shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n    # print error to STDERR\n    echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n    exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
+			showEnvVarsInLog = 0;
+		};
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+		2850C5F418D0F706002B7D0A /* Sources */ = {
+			isa = PBXSourcesBuildPhase;
+			buildActionMask = 2147483647;
+			files = (
+				283B59B7195334AF000828CD /* CustomSelectorsFormViewController.m in Sources */,
+				06377AFC1F87F3AB003D0078 /* TZTestCell.m in Sources */,
+				28A766551932F22400D69546 /* UsersTableViewController.m in Sources */,
+				3CDAFC7A1AB0AFA4000F75B6 /* CustomRowsViewController.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 */,
+				3C3B01F01AB74BDC0027CD45 /* FloatLabeledTextFieldCell.m in Sources */,
+				28DBB04118D76FDC00FB8A8B /* MultivaluedFormViewController.m in Sources */,
+				28A85D5918E346C100E81A26 /* XLFormImageSelectorCell.m in Sources */,
+				28468E9818EC686500DBB015 /* NativeEventFormViewController.m in Sources */,
+				06377AFA1F87F3AB003D0078 /* LxGridViewFlowLayout.m in Sources */,
+				3C3B01DA1AB7497D0027CD45 /* XLFormWeekDaysCell.m in Sources */,
+				06536E131F8870160066BC2F /* FYSectionCell.m in Sources */,
+				28F89F2E1AA4EA5600E90218 /* ValidationExamplesFormViewController.m in Sources */,
+				66B6266E1AE0055100007886 /* DateAndTimeValueTrasformer.m in Sources */,
+				3C3B01D51AB741EF0027CD45 /* XLFormRatingCell.m in Sources */,
+				28A7665E1932F61100D69546 /* DynamicSelectorsFormViewController.m in Sources */,
+				06377AFB1F87F3AB003D0078 /* TZPhotoCell.m in Sources */,
+				281E5BE919538F4A006D93C5 /* CLLocationValueTrasformer.m in Sources */,
+				2843EB5618D4F7B700F13E2B /* DatesFormViewController.m in Sources */,
+				283C6B7D1999BAF100A5283D /* UICustomizationFormViewController.m in Sources */,
+				3C3B01E21AB7499A0027CD45 /* XLRatingView.m in Sources */,
+				283B59B219532415000828CD /* MapViewController.m in Sources */,
+				2843EB4718D4915800F13E2B /* ExamplesFormViewController.m in Sources */,
+				BF01E9281C21F0BB00BDE045 /* XLFormInlineSegmentedCell.m in Sources */,
+				BF9DB1D61AE0436600B985E7 /* PredicateFormViewController.m in Sources */,
+				BFE91AFB1AE159B200DE5231 /* BasicPredicateViewController.m in Sources */,
+				DEB8235C1AD5529A00AF9FE2 /* FormattersViewController.m in Sources */,
+				2843EB5218D4CFC700F13E2B /* OthersFormViewController.m in Sources */,
+				2843EB4B18D496F600F13E2B /* SelectorsFormViewController.m in Sources */,
+				28468EA418EF41D300DBB015 /* InputsFormViewController.m in Sources */,
+				28A76625193251E500D69546 /* AppDelegate.m in Sources */,
+			);
+			runOnlyForDeploymentPostprocessing = 0;
+		};
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+		28468EA518EF594800DBB015 /* Localizable.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				28468EA618EF594800DBB015 /* en */,
+			);
+			name = Localizable.strings;
+			sourceTree = "<group>";
+		};
+		2850C60418D0F706002B7D0A /* InfoPlist.strings */ = {
+			isa = PBXVariantGroup;
+			children = (
+				2850C60518D0F706002B7D0A /* en */,
+			);
+			name = InfoPlist.strings;
+			sourceTree = "<group>";
+		};
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+		2850C62218D0F707002B7D0A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = NO;
+				ENABLE_TESTABILITY = YES;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_DYNAMIC_NO_PIC = NO;
+				GCC_OPTIMIZATION_LEVEL = 0;
+				GCC_PREPROCESSOR_DEFINITIONS = (
+					"DEBUG=1",
+					"$(inherited)",
+				);
+				GCC_SYMBOLS_PRIVATE_EXTERN = NO;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				ONLY_ACTIVE_ARCH = YES;
+				SDKROOT = iphoneos;
+			};
+			name = Debug;
+		};
+		2850C62318D0F707002B7D0A /* Release */ = {
+			isa = XCBuildConfiguration;
+			buildSettings = {
+				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+				CLANG_CXX_LIBRARY = "libc++";
+				CLANG_ENABLE_MODULES = YES;
+				CLANG_ENABLE_OBJC_ARC = YES;
+				CLANG_WARN_BOOL_CONVERSION = YES;
+				CLANG_WARN_CONSTANT_CONVERSION = YES;
+				CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+				CLANG_WARN_EMPTY_BODY = YES;
+				CLANG_WARN_ENUM_CONVERSION = YES;
+				CLANG_WARN_INT_CONVERSION = YES;
+				CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+				COPY_PHASE_STRIP = YES;
+				ENABLE_NS_ASSERTIONS = NO;
+				GCC_C_LANGUAGE_STANDARD = gnu99;
+				GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+				GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+				GCC_WARN_UNDECLARED_SELECTOR = YES;
+				GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+				GCC_WARN_UNUSED_FUNCTION = YES;
+				GCC_WARN_UNUSED_VARIABLE = YES;
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				SDKROOT = iphoneos;
+				VALIDATE_PRODUCT = YES;
+			};
+			name = Release;
+		};
+		2850C62518D0F707002B7D0A /* Debug */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = 5F6FC67A75254B60005DC716 /* Pods-XLForm.debug.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "XLForm/XLForm-Prefix.pch";
+				INFOPLIST_FILE = "XLForm/XLForm-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_BUNDLE_IDENTIFIER = "com.xmartlabs.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Debug;
+		};
+		2850C62618D0F707002B7D0A /* Release */ = {
+			isa = XCBuildConfiguration;
+			baseConfigurationReference = B98C1213E7C714A861219C81 /* Pods-XLForm.release.xcconfig */;
+			buildSettings = {
+				ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+				ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+				"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
+				GCC_PRECOMPILE_PREFIX_HEADER = YES;
+				GCC_PREFIX_HEADER = "XLForm/XLForm-Prefix.pch";
+				INFOPLIST_FILE = "XLForm/XLForm-Info.plist";
+				IPHONEOS_DEPLOYMENT_TARGET = 8.0;
+				PRODUCT_BUNDLE_IDENTIFIER = "com.xmartlabs.$(PRODUCT_NAME:rfc1034identifier)";
+				PRODUCT_NAME = "$(TARGET_NAME)";
+				TARGETED_DEVICE_FAMILY = "1,2";
+				WRAPPER_EXTENSION = app;
+			};
+			name = Release;
+		};
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+		2850C5F318D0F706002B7D0A /* Build configuration list for PBXProject "XLForm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2850C62218D0F707002B7D0A /* Debug */,
+				2850C62318D0F707002B7D0A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+		2850C62418D0F707002B7D0A /* Build configuration list for PBXNativeTarget "XLForm" */ = {
+			isa = XCConfigurationList;
+			buildConfigurations = (
+				2850C62518D0F707002B7D0A /* Debug */,
+				2850C62618D0F707002B7D0A /* Release */,
+			);
+			defaultConfigurationIsVisible = 0;
+			defaultConfigurationName = Release;
+		};
+/* End XCConfigurationList section */
+	};
+	rootObject = 2850C5F018D0F706002B7D0A /* Project object */;
+}

+ 7 - 0
Examples/Objective-C/XLForm.xcodeproj/project.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+   version = "1.0">
+   <FileRef
+      location = "self:XLForm.xcodeproj">
+   </FileRef>
+</Workspace>

+ 1 - 0
Examples/Objective-C/XLForm.xcworkspace/contents.xcworkspacedata

@@ -0,0 +1 @@
+<?xml version='1.0' encoding='UTF-8'?><Workspace version='1.0'><FileRef location='group:XLForm.xcodeproj'/><FileRef location='group:Pods/Pods.xcodeproj'/></Workspace>

BIN
Examples/Objective-C/XLForm/Images.xcassets/AlbumAddBtn.imageset/AlbumAddBtn@2x.png


+ 21 - 0
Examples/Objective-C/XLForm/Images.xcassets/AlbumAddBtn.imageset/Contents.json

@@ -0,0 +1,21 @@
+{
+  "images" : [
+    {
+      "idiom" : "universal",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "universal",
+      "filename" : "AlbumAddBtn@2x.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "universal",
+      "scale" : "3x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

+ 192 - 0
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/Contents.json

@@ -0,0 +1,192 @@
+{
+  "images" : [
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "20x20",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "29x29",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "40x40",
+      "scale" : "3x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "xl_appicon_57.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "57x57",
+      "idiom" : "iphone",
+      "filename" : "xl_appicon_114.png",
+      "scale" : "2x"
+    },
+    {
+      "size" : "60x60",
+      "idiom" : "iphone",
+      "filename" : "xl_appicon_120.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "iphone",
+      "size" : "60x60",
+      "scale" : "3x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "20x20",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "29x29",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "40x40",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "50x50",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "50x50",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "72x72",
+      "scale" : "1x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "72x72",
+      "scale" : "2x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "xl_appicon_76.png",
+      "scale" : "1x"
+    },
+    {
+      "size" : "76x76",
+      "idiom" : "ipad",
+      "filename" : "xl_appicon_152.png",
+      "scale" : "2x"
+    },
+    {
+      "idiom" : "ipad",
+      "size" : "83.5x83.5",
+      "scale" : "2x"
+    },
+    {
+      "size" : "24x24",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "notificationCenter",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "27.5x27.5",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "notificationCenter",
+      "subtype" : "42mm"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "watch",
+      "role" : "companionSettings",
+      "scale" : "2x"
+    },
+    {
+      "size" : "29x29",
+      "idiom" : "watch",
+      "role" : "companionSettings",
+      "scale" : "3x"
+    },
+    {
+      "size" : "40x40",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "appLauncher",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "44x44",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "longLook",
+      "subtype" : "42mm"
+    },
+    {
+      "size" : "86x86",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "quickLook",
+      "subtype" : "38mm"
+    },
+    {
+      "size" : "98x98",
+      "idiom" : "watch",
+      "scale" : "2x",
+      "role" : "quickLook",
+      "subtype" : "42mm"
+    },
+    {
+      "idiom" : "car",
+      "size" : "120x120",
+      "scale" : "1x"
+    }
+  ],
+  "info" : {
+    "version" : 1,
+    "author" : "xcode"
+  }
+}

BIN
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_114.png


BIN
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_120.png


BIN
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_152.png


BIN
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_57.png


BIN
Examples/Objective-C/XLForm/Images.xcassets/AppIcon.appiconset/xl_appicon_76.png


Some files were not shown because too many files changed in this diff