[
  {
    "path": ".github/FUNDING.yml",
    "content": "# These are supported funding model platforms\n\ngithub: xmartlabs # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]\npatreon: # Replace with a single Patreon username\nopen_collective: # Replace with a single Open Collective username\nko_fi: # Replace with a single Ko-fi username\ntidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel\ncommunity_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry\nliberapay: # Replace with a single Liberapay username\nissuehunt: # Replace with a single IssueHunt username\notechie: # Replace with a single Otechie username\nlfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry\ncustom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a report to help us improve. Please make sure to search for existing\n  issues or in the Readme before posting.\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior:\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Screenshots**\nIf applicable, add screenshots to help explain your problem.\n\n**Versions (please complete the following information):**\n - Device: [e.g. iPhone 13]\n - OS: [e.g. iOS 15.0]\n - Eureka Version [e.g. 5.3.5]\n - Xcode version [e.g. 13.1]\n\n**Additional context**\nAdd any other context about the problem here. Console output, stack traces, etc.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: 'type: feature request'\nassignees: ''\n\n---\n\n**Before submitting...**\nPlease check whether such a feature has already been requested.\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context or screenshots about the feature request here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE.md",
    "content": "Before submitting issues ...\n\n- Make sure you are using Eureka [latest release](https://github.com/xmartlabs/Eureka/releases) or master branch version.\n- Make sure your Xcode version is the latest stable one.\n- Check if the issue was [already reported or fixed](https://github.com/xmartlabs/Eureka/issues?utf8=%E2%9C%93&q=is%3Aissue). We add labels to each issue in order to easily find related issues. If you found a match add a brief comment \"I have the same problem\" or \"+1\".\n\nWhen submitting issues, please provide the following information to help maintainers to fix the problem faster:\n\n- Environment: Eureka, Xcode and iOS version you are using.\n- In case of reporting errors, provide Xcode console output of stack trace or code compilation error.\n- Any other additional detail such as your eureka form/section/row code that you think it would be useful to understand and solve the problem.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE.md",
    "content": ""
  },
  {
    "path": ".github/workflows/ci.yml",
    "content": "name: Eureka CI\n\non:\n  pull_request:\n  push:\n    branches:\n      - master\n\njobs:\n  iOS:\n    runs-on: macos-12\n    strategy:\n      matrix:\n        destination: ['platform=iOS Simulator,OS=16.0,name=iPhone 14']\n\n    steps:\n    - uses: actions/checkout@v2\n    - uses: maxim-lobanov/setup-xcode@v1\n      with:\n        xcode-version: '14.0.1'\n    - name: Build and test\n      run: set -o pipefail && xcodebuild -project Eureka.xcodeproj -scheme 'Eureka' -sdk 'iphonesimulator' -destination \"${{ matrix.destination }}\" -configuration Debug test | xcpretty\n"
  },
  {
    "path": ".gitignore",
    "content": "# Xcode\n#\nbuild/\n*.pbxuser\n!default.pbxuser\n*.mode1v3\n!default.mode1v3\n*.mode2v3\n!default.mode2v3\n*.perspectivev3\n!default.perspectivev3\nxcuserdata\n*.xccheckout\n*.moved-aside\nDerivedData\n*.hmap\n*.ipa\n*.xcuserstate\n*.xcscmblueprint\n.LSOverride\n\n# CocoaPods\n#\n# We recommend against adding the Pods directory to your .gitignore. However\n# you should judge for yourself, the pros and cons are mentioned at:\n# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control\n#\n# Pods/\n\n# Carthage\n#\n# Add this line if you want to avoid checking in source code from Carthage dependencies.\n# Carthage/Checkouts\n\nCarthage/Build\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Change Log\nAll notable changes to this project will be documented in this file.\n\n\n### [5.5.0](https://github.com/xmartlabs/Eureka/releases/tag/5.5.0)\n\n* Created PrivacyInfo file (#2255)\n\n### [5.4.0](https://github.com/xmartlabs/Eureka/releases/tag/5.4.0)\n\n* Renamed several methods that clashed with private Obj-C methods and triggered warnings when uploading to App Store (#2231)\n* Other minor fixes (#2220, #2222)\n\n### [5.3.6](https://github.com/xmartlabs/Eureka/releases/tag/5.3.6)\n\n* Fixed done button issue in keyboard (#2213)\n\n### [5.3.5](https://github.com/xmartlabs/Eureka/releases/tag/5.3.5)\n\n* Fix a compiler error in Xcode 13 (#2162)\n* Change CI to GitHub Actions and remove Travis (#2185)\n* Fix crash when user taps tab key on external keyboard (#2205)\n* Other minor fixes (#2191, #2206, #2183)\n\n### [5.3.4](https://github.com/xmartlabs/Eureka/releases/tag/5.3.4)\n\n* Resolve class protocol inheritance warnings (#2151)\n* Fix Chinese input issue (#2150) …\n* Specific special characters are allowed in the username of an email address (#2160)\n* Fix SliderRow not rendering properly (#2166)\n\n### [5.3.3](https://github.com/xmartlabs/Eureka/releases/tag/5.3.3)\n\n* Add option for different ScrollPosition behavior on keyboard appearance (#2112)\n* Prefix Eureka to certain class names to avoid clashes with other pods (#2113)\n* Remove the default header title of section (#2128)\n* Modify hugging priority for PasswordRow (#2129)\n* Add replace method for all sections (#2105)\n* Fix: Non-public API usage (valueChanged, datePickerValueChanged) (#2130)\n* Fix: remove EXCLUDED_ARCHS build setting to support M1 mac iphone simulator (#2137)\n* Fix: removeAll method in sections (#2141)\n\n\n### [5.3.2](https://github.com/xmartlabs/Eureka/releases/tag/5.3.2)\n\n* Make tableViewStyle public (#2092)\n* Fix CountDown rows crash (#2095)\n* Make ValidationRuleHelper's rule property public. (#2101)\n* Fix for building with Carthage and Xcode 12 (#2104)\n\n### [5.3.1](https://github.com/xmartlabs/Eureka/releases/tag/5.3.1)\n\n* Fix building for Mac Catalyst on Xcode 12 (#2078)\n* Fix datePickerStyle for DateFieldRow and DatePickerCell (#2077)\n* Adjust font size of PasswordRow to avoid dots (#2080)\n\n### [5.3.0](https://github.com/xmartlabs/Eureka/releases/tag/5.3.0)\n\n* Reload rows on viewWillAppear for iOS 12 and below. (#2029)\n* Change validation functions access level to open (#2049)\n* Start editing field rows at the end when tapping blank space in row (#2046)\n* Update SelectorViewController.swift (#2062)\n* Fix subtitle field row constraints (#2069)\n* Create a workaround for Swift crash (#2057, #2061)\n* Fix date row style/rendering issues for iOS 14 (#2067)\n\n### [5.2.1](https://github.com/xmartlabs/Eureka/releases/tag/5.2.1)\n\n* Mark `tableView:editActionsForRowAt` as deprecated (#2000)\n* Removes unwanted assertionFailure Core.swift Navigation (#1998)\n* Fix for crash in iOS 13.4 with Xcode 11.4 (#2008)\n\n### [5.2.0](https://github.com/xmartlabs/Eureka/releases/tag/5.2.0)\n\n* *Support for Swift Package Manager* (#1976)\n* Add GenericMultivaluedSection to allow changing add button (#1843)\n* Remove InputTypeInitiable constraint for PickerInputRow (#1975)\n* Fix: avoid reloading rows in viewWillAppear when tableView is not added to window (#1971)\n* Fix optional header and footer in SelectorViewController. (#1962)\n* Fix table view contentInset adjustment with safe area when keyboard shows (#1960)\n* Fix for iOS 13 that was not removing the row automatically anymore even after calling the completion handler in a destructive swipe action (#1944)\n* Fixed reference cycle (#1930)\n* Allows a section's header and footer to be `nil` (#1927)\n\n### [5.1.0](https://github.com/xmartlabs/Eureka/releases/tag/5.1.0)\n\n* Support for Xcode 11 and iOS 13\n* Added dark mode support\n\n### [5.0.1](https://github.com/xmartlabs/Eureka/releases/tag/5.0.1)\n\n* Added `quietly` parameter for use with non-ui validation (#1817)\n* RuleMinLength (and others) now pass for nil and empty strings.\n* iOS deployment target back on iOS 9.0\n* Several other fixes\n\n### [5.0.0](https://github.com/xmartlabs/Eureka/releases/tag/5.0.0)\n\n* Bug fixes and stability improvements\n* iOS deployment target increased to iOS9.3\n\n### [4.3.1](https://github.com/xmartlabs/Eureka/releases/tag/4.3.1)\n\n* Bug fixes and stability improvements\n\n\n### [4.3.0](https://github.com/xmartlabs/Eureka/releases/tag/4.3.0)\n\n* Changes for Swift 4.2, Xcode 10 and iOS 12\n* Add ability to customise the text color of UIPickerView used by PickerRow\n* Make `onPresent` result discardable\n* Add `insert(row: after:)` method on Section which allows inserting rows after a hidden row\n* Other minor fixes\n\n### [4.2.0](https://github.com/xmartlabs/Eureka/releases/tag/4.2.0)\n\n* Adding support for RowType.subtitle on FieldRow (#1468)\n* CompletionHandler for SwipeAction under iOS < 11\n* Allow setting position of the cell after scrolling (#1452)\n* Add Chinese readme (#1487)\n* Implement readOnly textAreaRow feature (#1489)\n* Update cell when tintColor changes (#1492)\n* PickerRow for 2 and 3 components (#1540)\n* And several bug fixes\n\n### [4.1.1](https://github.com/xmartlabs/Eureka/releases/tag/4.1.1)\n\n* Bug fixes and stability improvements.\n\n### [4.1.0](https://github.com/xmartlabs/Eureka/releases/tag/4.1.0)\n\n* Add compatibility for Xcode 9.3 beta 2 and Swift 4.1.\n* New functionality 🎉. https://github.com/xmartlabs/eureka#swipe-actions. Thanks [@marbetschar](https://github.com/marbetschar).\n* Add sectionIndexTitles and sectionForSectionIndexTitles to FormViewController to allow for subclasses to override.\n* Fix SliderRow layout.\n* Fix regular expression for URLs to allow query and location parameter.\n* Corrected issue in section sorting function of MultipleSelectorViewController, where all options were placed in one section, with a section title based on the first option.\n* Added missing call to super.updateConstraints in SegmentedCell.\n* Add ability to setup alert cancel title from AlertRow.\n* remove blank section headers/footers from plain tables on iOS 11. This prevents blank section headers and footers from appearing on iOS\n11 when setting the table view style to plain and there are no headers\nor footers.\n* Fix UIDatePicker bug when mode == .countDownTimer.\n* Allow non-selectable rows to exist besides selectable rows in a selectable section.\n* SliderRow - added option 'shouldHideValue' to hide value label (default to false).\n* Update cell when tintColor changes.\n* Support dynamic font size changes.\n\n### [4.0.0](https://github.com/xmartlabs/Eureka/releases/tag/4.0.0)\n\n* Xcode 9, Swift 4 support.\n* Add the values of MultivaluedSection into form.values().\n\n### [3.1.0](https://github.com/xmartlabs/Eureka/releases/tag/3.1.0)\n\nBug fixes & stability improvements:\n\n* Fixed how sections and rows are inserted using subscripts\n* Fixed issue with disbled rows in selectable sections. Disabled rows were still selectable.\n* Multivalued section does not display image in imagerow #977\n* Improve currency formatter #1103\n* Added option to use accessory view in ImageCheckCell\n* Exact length validation (new feature)\n* Change validation on demand behaviour when row was not valid (#1148)\n* Move FormDelegate methods to `FormViewController` class to make it extensible and customizable.\n* The slider was not being disabled when the row was disabled.\n\n\n\n### [3.0.0](https://github.com/xmartlabs/Eureka/releases/tag/3.0.0)\n\nBug fixes & stability improvements:\n\n* CountDownRow prints Date as Optional #683\n* defaultOnCellHighlightChanged event not being called #704\n* Error when compiling CustomRow with Swift 3.0 #693\n* Fix strange animation when using `insertAtIndex` to add a new section to the form. #566\n* Ability to customize validation message.\n* New RuleEqualsToRow validation rule.\n* fix RuleMaxLength & RuleMinLength issues. #729\n* avoid `animateAlongsideTransition(in:` that could cause transition animation interruption.\n* Fix initialisation of SliderRow when it has no value at start.\n* Added isExpanded & isCollapsed helpers to InlineRowType.\n* fix #800, added form.validate() argument to indicate if hiddenRows should be considered.\n* Fix issue when showing StepperRow value. Now we use displayValueFor as we do with the rest of rows.\n* Added PickerInputRow #818\n* Fix an issue when FieldCell has a Formatter and the formatter is not used during text editing #796, #768\n* Tapping inside an enabled text area row crashes #795\n* Added ability to change scroll position when a row is selected.\n* Added ability to specify that regex validation allows empty values.\n* Changed the Access Control of Class RuleRegExp to be open.\n* Implement init?(coder: NSCoder) for some cell types #860\n* Removed fatalError from init(coder:) for selector view controllers #882\n* Always call onSelectSelectableRow, added properties to control selector vc dismissal.\n* Reload the tableView even if it is not added to a window.\n* Adds 'cell.row.wasChanged' to check for cell validation.\n* Added ability to group options of PushRow MultipleSelectorRow by adding sections to the selector table view.\n* fix #887, TextAreaRow adds an enter when pressing next on keyboard coming from another row.\n* Minor fix on how SliderRow update method is called.\n* Adds RuleClosure example in code comments.\n* Removing the forced navigationAccessoryView.tintColor set #921.\n\nThanks to all contributors!! 🍻🍻🍻🍻🍻🍻\n\n### [2.0.1](https://github.com/xmartlabs/Eureka/releases/tag/2.0.1)\n\n* Bug fixes and stability improvements.\n\n### [2.0.0-beta.1](https://github.com/xmartlabs/Eureka/releases/tag/2.0.0)\n\nPull requests associated with this milestone can be found in this [filter](https://github.com/xmartlabs/Eureka/issues?utf8=%E2%9C%93&q=milestone%3A2.0.0%20).\n\nWe have made tons of changes to the Eureka API to follow the new Swift API design guidelines.\nIt's hard to enumerate all changes and most of them will be automatically suggested by Xcode.\n\nWe have also added to Eureka a extensible build-in validations support.\n\nThese are the most important changes...\n\n#### Deleted\n\n* `PostalAddressRow` was removed.\n* `ImageRow` was removed.\n\nYou can find these both rows under [EurekaCommunity] github organization.\n\n* Row's `func highlightCell()`\n* Row's `func unhighlightCell()`\n* Cell's `func highlight()`\n* Cell's `func unhighlight()`\n* Cell's `func didSelect()`\n\n#### Added\n\n* Rows's `var isHighlighted: Bool`.\n* Rows's `var isValid: Bool`.\n* Row's `func onCellHighlightChanged(_ callback: @escaping (_ cell: Cell, _ row: Self)->()) -> Self `.\n* Row's `func onRowValidationChanged(_ callback: @escaping (_ cell: Cell, _ row: Self)->()) -> Self`.\n* Row's `func validate() -> [ValidationError]`\n* Form's `func validate() -> [ValidationError]`\n* Row's `func add<Rule: RuleType>(rule: Rule)`\n* Row's `func remove(ruleWithIdentifier: String)`\n* `RuleSet<T: Equatable>` type.\n* `ValidationOptions` Enum type.\n* `RuleType` protocol.\n* `ValidationError` type.\n\n##### Fixes\n\n* Fixed textlabel alignment for cells with custom constraints (FieldRow, SegmentedRow, TextAreaRow).\n* Set 'Require Only App-Extension-Safe API' to YES to enable code sharing in App Extensions.\n* Other bug fixes and minor improvements\n\nTake a look at [2.0.0 Migration guide]() for more information on how to solve breaking changes.\n\n### [1.7.0](https://github.com/xmartlabs/Eureka/releases/tag/1.7.0)\n\n* **Breaking change**: Fixed typo in `hightlightCell`. You must now call / override `highlightCell`.\n* Added `allSections` method to Form. (by @programmarchy)\n* Updated navigation images for row navigation. (thanks @VladislavJevremovic)\n* Removed +++= operator.\n* Other bug fixes and minor improvements\n\n### [1.6.0](https://github.com/xmartlabs/Eureka/releases/tag/1.6.0)\n\n* **Breaking change**: Remove controller: FormViewController parameter from HeaderFooterViewRepresentable `viewForSection` method.\n\n\n* Support for Xcode 7.3.1.\n* Fixed ImageRow issue when trying to access imageURL after selecting image. Now imageURL is properly set up. #346\n* Made FieldRowConformance protocol public.\n* Added ability to override TextAreaRow constraints.\n* Fix. Now section headerView/footerView cache is deleted whenever section header/footer is assigned.\n* Made public `navigateToDirection(direction: Direction)` method.\n* Fixed autolayout in cells. #396\n* Removed cell.setNeedsLayout() and cell.setNeedsUpdateConstraints() from updateCell process.\n* Added `ButtonRow` `onCellSelecttion` example.\n* Improve row deselection behavior during interactive transitions. #406\n* Autosize TextAreaRow functionality added.\n* Moved `inputAccessoryViewForRow` method from extension to FormViewController allowing it to be overridden.\n* Added ability to show a text when there is no value selected to some rows.\n* Fixed: The top divider of a PickerInlineRow disappears upon selection.\n* Fixed crash when selecting a date. DatePickerRow.\n* Ensure inline row is visible when it’s expanded.\n* Fixed PostalAddressRow - When a long form is scrolled up/down, values in Address box disappears.\n\n### [1.5.0](https://github.com/xmartlabs/Eureka/releases/tag/1.5.0)\n\n* Xcode 7.3 support.\n* Expose a public `KeyboardReturnTypeConfiguration` initializer.\n* Allow to override constraints of FieldRow.\n* Fixed SelectableSection wrong behaviour when the selectable rows was added to the section before adding the selectable section to the form.\n* Implemented StepperRow and added an example to the example project.\n* Allow AlertRow cancel title to be changed.\n* Enabled CI UI testing and added some tests.\n* Fixed \"0 after decimal separator (DecimalRow)\"\n* Added ability to customize selector and multiple selector view controller option rows. Added `selectableRowCellUpdate` property to `SelectorViewController` and `MultipleSelectorViewController`.\n* Performance improvement. Store values for each tag in a dictionary and do not calculate it every time we evaluateHidden.\n\n### [1.4.1](https://github.com/xmartlabs/Eureka/releases/tag/1.4.1)\nReleased on 2016-02-25.\n\n##### Breaking Changes\n\n* `SelectorRow` now requires the cell among its generic values. This means it is easier to change the cell for a selector row.\n* `_AlertRow` and `_ActionSheetRow` require generic cell parameter\n\nIf you are using custom rows that inherit from SelectorRow then you might want to change them as follows (or use your custom cell):\n```\n// before\n// public final class LocationRow : SelectorRow<CLLocation, MapViewController>, RowType\n// now\npublic final class LocationRow : SelectorRow<CLLocation, MapViewController, PushSelectorCell<CLLocation>>, RowType\n```\n\n\n### [1.4.0](https://github.com/xmartlabs/Eureka/releases/tag/1.4.0)\nReleased on 2016-02-25.\n\n * PopoverSelectorRow added.\n * BaseRow reload, select, deselect helpers added.\n * ImageRow update: allows clear button, image sources are public\n * Added PostalAddressRow\n * Lots of smaller bug fixes and new documentation\n\n##### Breaking Changes\n\n* `BaseCellType` protocol method `func cellBecomeFirstResponder() -> Bool`  was renamed to `func cellBecomeFirstResponder(direction: Direction) -> Bool`\n\nIf you are using custom rows you may have to fix the compiler error by adding the new parameter.\n\n* DecimalRow value type changed from Float to Double.\n\n### [1.3.1](https://github.com/xmartlabs/Eureka/releases/tag/1.3.1)\nReleased on 2016-01-11.\n\n * Bug fixes and stability improvements.\n\n### [1.3.0](https://github.com/xmartlabs/Eureka/releases/tag/1.3.0)\nReleased on 2015-12-08.\n\n * Memory leak fix.\n * Removed HeaderFooterView inits from Section.\n * Removed HeaderFooterView inits from Section\n * Added documentation for Section Header and Footer\n * Added documentation for Implementing custom Presenter row\n * Inject table view style on init (by [mikaoj])\n * Modified observeValueForKeyPath functions on FieldCell and SegmentedCell to correctly update constraints (by [dernster] and [estebansotoara])\n * Added Keyboard next button\n * Fixed bug with minimum dates [#111](https://github.com/xmartlabs/Eureka/issues/111)\n * Fixed bug where autocorrected value would not be saved in row.value\n * Fixed currency formatter bugs\n * Added list sections\n\n### [1.2.0](https://github.com/xmartlabs/Eureka/releases/tag/1.2.0)\nReleased on 2015-11-12.\n\n * Added PickerRow.\n * Added PickerInlineRow.\n * Added ZipCodeRow.\n * Fix bug when inserting hidden row in midst of a section.\n * Example project: Added ability to set up a formatter to FloatLabelRow.\n * `rowValueHasBeenChanged` signature has been changed to `override func rowValueHasBeenChanged(row: BaseRow, oldValue: Any?, newValue: Any?)`.\n * Added `@noescape` attribute to initializer closures.\n * Fixed issue with tableView's bottom inset when keyboard was dismissed.\n * Changed NameRow keyboardType to make autocapitalization works.\n\n### [1.1.0](https://github.com/xmartlabs/Eureka/releases/tag/1.1.0)\nReleased on 2015-10-20.\n\n### [1.0.0](https://github.com/xmartlabs/Eureka/releases/tag/1.0.0)\nReleased on 2015-09-29. This is the initial version.\n\n\n\n\n\n[mikaoj]: https://github.com/mikaoj\n[estebansotoara]: https://github.com/estebansotoara\n[dernster]: https://github.com/dernster\n[EurekaCommunity]: https://github.com/EurekaCommunity\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "Contributing Guidelines\n--------------------------------------------------\n\nThis document provides general guidelines about how to contribute to the project. Keep in mind these important things before you start contributing.\n\n### Asking Questions\n\nWe do not use github issues for general library support. We think this questions should be posted on stack overflow using [eureka-forms](http://stackoverflow.com/questions/tagged/eureka-forms) tag.\n\n### Reporting issues\n\n* Use [github issues](https://github.com/xmartlabs/Eureka/issues) to report a bug.\n* Before creating a new issue:\n  * Make sure you are using the [latest release](https://github.com/xmartlabs/Eureka/releases).\n  * Check if the issue was [already reported or fixed](https://github.com/xmartlabs/Eureka/issues?utf8=%E2%9C%93&q=is%3Aissue). Notice that it may not be released yet.\n  * If you found a match add a brief comment \"I have the same problem\" or \"+1\". This helps prioritize the issues addressing the most common and critical first. If possible add additional information to help us reproduce and fix the issue. Please use your best judgement.    \n* Reporting issues:\n  * Please include the following information to help maintainers to fix the problem faster:\n    * Xcode version you are using.\n    * iOS version you are targeting.\n    * Full Xcode console output of stack trace or code compilation error.\n    * Any other additional detail you think it would be useful to understand and solve the problem.\n\n\n### Pull requests\n\nThe easiest way to start contributing is searching open issues by `help wanted` tag. We also add a `difficulty` tag (difficulty: easy, difficulty: moderate, difficulty: hard) in order to give an idea of how complex it can be to implement the feature according maintainers project experience.\n\n* Add test coverage to the feature or fix. We only accept new feature pull requests that have related test coverage. This allows us to keep the library stable as we move forward.\n* Remember to document the new feature. We do not accept new feature pull requests without its associated documentation.\n* In case of a new feature please update the example project showing the feature.\n* Please only one fix or feature per pull request. This will increase the chances your feature will be merged.\n\n\n###### Suggested git workflow to contribute\n\n1. Fork the Eureka repository.\n2. Clone your forked project into your developer machine: `git clone git@github.com:<your-github-username>/Eureka.git`\n3. Add the original project repo as upstream repository in your forked project: `git remote add upstream git@github.com:xmartlabs/Eureka.git`\n4. Before starting a new feature make sure your forked master branch is synchronized upstream master branch. Considering you do not merge your pull request into master you can run: `git checkout master` and then `git pull upstream master`. Optionally `git push origin master`.\n5. Create a new branch. Note that the starting point is the upstream master branch HEAD. `git checkout -b my-feature-name`\n6. Stage all your changes `git add .` and commit them `git commit -m \"Your commit message\"`\n7. Make sure your branch is up to date with upstream master, `git pull --rebase upstream master`, resolve conflicts if necessary. This will move your commit to the top of git stack.\n8. Squash your commits into one commit. `git rebase -i HEAD~6` considering you did 6 commits.\n9. Push your branch into your forked remote repository.\n10. Create a new pull request adding any useful comment.\n\n\n###### Code style and conventions\n\nWe try to follow our [swift style guide](https://github.com/xmartlabs/Swift-Style-Guide). Following it is not strictly necessary to contribute and to have a pull request accepted but project maintainers try to follow it. We would love to hear your ideas to improve our code style and conventions. Feel free to contribute.\n\n\n### Feature proposal\n\nWe would love to hear your ideas and make a discussions about it.\n\n* Use github issues to make feature proposals.\n* We use `type: feature request` label to mark all [feature request issues](https://github.com/xmartlabs/Eureka/labels/type%3A%20feature%20request).\n* Before submitting your proposal make sure there is no similar feature request. If you found a match feel free to join the discussion or just add a brief \"+1\" if you think the feature is worth implementing.\n* Be as specific as possible providing a precise explanation of feature request so anyone can understand the problem and the benefits of solving it.\n"
  },
  {
    "path": "Documentation/Eureka 2.0 Migration  Guide.md",
    "content": "# Eureka 2.0 Migration  Guide\n\n#### Requirements:\n\nEureka 2.0.0 needs Xcode 8, Swift3+ to work. Minimum supported iOS version is 8.0.\n\n#### Changes\n\nEureka 2.0.0 includes complete Swift 3 Compatibility and adopts the new [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/). It also includes the whole new validations build-in feature.\nBring support to swift 3 involves some API updates to follow Apple's Swift API best practices, we have also changed and deprecated some API's.\n\nMost important changes will be listed below...\n\n\nMany properties, methods, types were renamed and Xcode should suggest the fix automatically.\n\n\n\nThese are some examples:\n\n|Old API| New API|\n|----|----|\n|`func rowByTag<T: Equatable>(_: String) -> RowOf<T>?`|`func rowBy<T: Equatable>(tag: String) -> RowOf<T>?`|\n|`func rowByTag<Row: RowType>(_: String) -> Row?`|`func rowBy<Row: RowType>(tag: String) -> Row?`|\n|`func rowByTag(_: String) -> BaseRow?`|`func rowBy(tag: String) -> BaseRow?`|\n|`func sectionByTag(_: String) -> Section?`|`func sectionBy(tag: String) -> Section?`|\n|`func rowValueHasBeenChanged(_: BaseRow, oldValue: Any?, newValue: Any?)`|`func valueHasBeenChanged(for: BaseRow, oldValue: Any?, newValue: Any?)`|\n|`public final func indexPath() -> IndexPath?`|`public final var indexPath: IndexPath?`|\n|`func prepareForSegue(_ segue: UIStoryboardSegue)`|`func prepare(for segue: UIStoryboardSegue)`|\n|`func presentViewController(_ viewController: VCType!, row: BaseRow, presentingViewController:FormViewController)`|`present(_ viewController: VCType!, row: BaseRow, presentingViewController:FormViewController)`|\n|`func createController() -> VCType?`|`func makeController() -> VCType?`|\n\n\nThere are also some breaking changes related with deprecated API:\n\nRemoved APIs:\n\n* `PostalAddressRow` and `ImageRow` was deleted. You can find them and many other custom rows at EurekaCommunity [organization account](https://github.com/eurekaCommunity).\n* `highlightCell` and `unhighlightCell` callbacks were deleted, now we should use `row.isHighlighted` from cell update to check from highlighted status and make UI modification according its value.\n\nIn case you want to do something when the row's highlighted state switches its value you can set up `onCellHighlightChanged` callback.\n\nCustom Rows changes:\n\nRow generic type no longer specify the value type. Its Value type is inferred from cell specification.\n\nBefore:\n\n`public final class WeekDayRow: Row<Set<WeekDay>, WeekDayCell>, RowType`\n\n\nAfter:\n\n`public final class WeekDayRow: Row<WeekDayCell>, RowType`\n"
  },
  {
    "path": "Documentation/README_CN.md",
    "content": "![Eureka: 一个优雅的用Swift编写的表单生成框架](../Eureka.jpg)\n\n<p align=\"center\">\n<a href=\"https://travis-ci.org/xmartlabs/Eureka\"><img src=\"https://travis-ci.org/xmartlabs/Eureka.svg?branch=master\" alt=\"Build status\" /></a>\n<img src=\"https://img.shields.io/badge/platform-iOS-blue.svg?style=flat\" alt=\"Platform iOS\" />\n<a href=\"https://developer.apple.com/swift\"><img src=\"https://img.shields.io/badge/swift4-compatible-4BC51D.svg?style=flat\" alt=\"Swift 4 compatible\" /></a>\n<a href=\"https://github.com/Carthage/Carthage\"><img src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage compatible\" /></a>\n<a href=\"https://cocoapods.org/pods/Eureka\"><img src=\"https://img.shields.io/cocoapods/v/Eureka.svg\" alt=\"CocoaPods compatible\" /></a>\n<a href=\"https://raw.githubusercontent.com/xmartlabs/Eureka/master/LICENSE\"><img src=\"http://img.shields.io/badge/license-MIT-blue.svg?style=flat\" alt=\"License: MIT\" /></a>\n<a href=\"https://codebeat.co/projects/github-com-xmartlabs-eureka\"><img alt=\"codebeat badge\" src=\"https://codebeat.co/badges/16f29afb-f072-4633-9497-333c6eb71263\" /></a>\n</p>\n\n由[XMARTLABS](http://xmartlabs.com)精心编写，是[XLForm]的Swift版本。\n\n## 概览\n\n<table>\n  <tr>\n    <th>\n      <img src=\"../Example/Media/EurekaExample1.gif\" width=\"220\"/>\n    </th>\n    <th>\n      <img src=\"../Example/Media/EurekaExample2.gif\" width=\"220\"/>\n    </th>\n    <th>\n    <img src=\"../Example/Media/EurekaExample3.gif\" width=\"220\"/>\n    </th>\n  </tr>\n</table>\n\n## 目录\n\n* [要求]\n* [使用]\n  + [如何创建表格]\n  + [获取行的值]\n  + [操作符]\n  + [callbacks的使用]\n  + [Section Header和Footer]\n  + [动态地隐藏和显示row(或者Sections)]\n  + [列表类型的sections]\n  + [有多个值的sections]\n  + [验证]\n  + [滑动操作]\n* [自定义row]\n  + [简单的自定义rows]\n  + [自定义内联rows]\n  + [自定义Presenter rows]\n* [row目录]\n* [安装]\n* [常见问题解答]\n\n**想了解更多，可以查看我们的关于*Eureka*的[博客](https://blog.xmartlabs.com/2015/09/29/Introducing-Eureka-iOS-form-library-written-in-pure-Swift/)。**\n\n## 要求\n\n* Xcode 9.2+\n* Swift 4+\n\n### 示例程序\n\n你可以clone这个项目，然后运行Example来欣赏Eureka的大部分特性。\n\n<table>\n  <tr>\n    <th>\n      <img src=\"../Example/Media/EurekaNavigation.gif\" width=\"200\"/>\n    </th>\n    <th>\n      <img src=\"../Example/Media/EurekaRows.gif\" width=\"200\"/>\n    </th>\n  </tr>\n</table>\n\n## 使用\n\n### 如何创建表格\n通过继承 `FormViewController`，你可以很容易地把sections和rows添加到`form`变量。\n\n```swift\nimport Eureka\n\nclass MyFormViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form +++ Section(\"Section1\")\n            <<< TextRow(){ row in\n                row.title = \"Text Row\"\n                row.placeholder = \"Enter text here\"\n            }\n            <<< PhoneRow(){\n                $0.title = \"Phone Row\"\n                $0.placeholder = \"And numbers here\"\n            }\n        +++ Section(\"Section2\")\n            <<< DateRow(){\n                $0.title = \"Date Row\"\n                $0.value = Date(timeIntervalSinceReferenceDate: 0)\n            }\n    }\n}\n```\n\n在这个例子中，我们创建了两个包含基本rows的sections，效果如下图：\n\n<center>\n<img src=\"../Example/Media/EurekaHowTo.gif\" width=\"200\" alt=\"Screenshot of Custom Cells\"/>\n</center>\n\n你也可以不继承`FormViewController`，然后自己设置`form`变量。但是通过继承的话，会方便很多。\n\n#### 配置键盘导航辅助\n\n如果需要改变导航辅助，你需要设置控制器的`navigationOptions`变量，是一个`OptionSet`类型，所以我们可以给它设置一个或者多个值：\n\n- **disabled**: 不显示\n- **enabled**: 显示在底部\n- **stopDisabledRow**: 如果下一行被禁用了，就隐藏\n- **skipCanNotBecomeFirstResponderRow**: 如果当前行的`canBecomeFirstResponder()`返回`false`，导航辅助就跳过这行\n\n默认值是 `enabled & skipCanNotBecomeFirstResponderRow`\n\n如果需要流畅的滚动屏幕，要把`animateScroll`设置为`true`。默认情况下，在导航辅助上点击上一个和下一个按钮的时候，`FormViewController`是直接跳到上一行或者下一行的，包括上一行或者下一行不在屏幕内的时候。\n\n如果要设置键盘和正在编辑的row的间距，设置`rowKeyboardSpacing`即可。默认情况下，当表格滚动到一个没有显示出来的view，键盘的顶部和编辑行的底部是没有间距的。\n\n```swift\nclass MyFormViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form = ...\n\n\t// 开启导航辅助，并且遇到被禁用的行就隐藏导航\n\tnavigationOptions = RowNavigationOptions.Enabled.union(.StopDisabledRow)\n\t// 开启流畅地滚动到之前没有显示出来的行\n\tanimateScroll = true\n\t// 设置键盘顶部和正在编辑行底部的间距为20\n\trowKeyboardSpacing = 20\n    }\n}\n```\n\n如果你想要改变导航辅助，需要在`FormViewController`的子类重写`navigationAccessoryView`。\n\n\n### 获取行的值\n\n`Row`对象有一个具体类型的 ***value*** 。\n例如，`SwitchRow`有一个`Bool`，而`TextRow`有一个`String`。\n\n```swift\n// 获取单个row的值\nlet row: TextRow? = form.rowBy(tag: \"MyRowTag\")\nlet value = row.value\n\n// 获取表格中所有rows的值(必须给每个row的tag赋值)\n// 字典中包含的键值对为：['rowTag': value]。\nlet valuesDictionary = form.values()\n```\n\n### 操作符\n\nEureka包含了自定义的操作符，使得我们更容易地创建表格：\n\n#### +++ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;添加一个section\n```swift\nform +++ Section()\n\n// 连起来添加多个sections\nform +++ Section(\"First Section\") +++ Section(\"Another Section\")\n\n// 或者直接利用行来创建一个空白的section\nform +++ TextRow()\n     +++ TextRow()  // 每个row显示在一个独立的section\n```\n\n#### <<< &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;插入一行\n\n```swift\nform +++ Section()\n        <<< TextRow()\n        <<< DateRow()\n\n// 或者隐式地创建一个section\nform +++ TextRow()\n        <<< DateRow()\n```\n\n#### += &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 添加一个数组\n\n```swift\n// 添加多个Sections到表格中\nform += [Section(\"A\"), Section(\"B\"), Section(\"C\")]\n\n// 添加多个rows到一个section中\nsection += [TextRow(), DateRow()]\n```\n\n### callbacks的使用\n\nEureka包含了很多callbacks来更改行的外观和行为。\n\n#### 理解`Row`和`Cell`\n\n`Row`是抽象的，是Eureka用来存储 **value** 的并包含了一个`Cell`。这个`Cell`用来管理view，并继承自`UITableViewCell`。\n\n例子:\n\n```swift\nlet row  = SwitchRow(\"SwitchRow\") { row in      // 初始化函数\n                        row.title = \"The title\"\n                    }.onChange { row in\n                        row.title = (row.value ?? false) ? \"The title expands when on\" : \"The title\"\n                        row.updateCell()\n                    }.cellSetup { cell, row in\n                        cell.backgroundColor = .lightGray\n                    }.cellUpdate { cell, row in\n                        cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)\n                }\n```\n\n<img src=\"../Example/Media/EurekaOnChange.gif\" width=\"300\" alt=\"Screenshot of Disabled Row\"/>\n\n#### Callbacks清单\n\n* **onChange()**\n\n\t当row的`value`改变时调用。你可以在这里调整一些参数，甚至显示或隐藏其他row。\n\n* **onCellSelection()**\n\n\t当用户点击row并且被选中的时候调用。\n\n* **cellSetup()**\n\n\t当cell第一次配置的时候调用，并且仅调用一次。可以在这做一些永久性的设置。\n\n* **cellUpdate()**\n\n\t当cell每次在屏幕上显示的时候调用。可以在里个更新外观。\n\n* **onCellHighlightChanged()**\n\n  当cell或者里面的subview 成为或者辞去第一响应者 时调用。\n\n* **onRowValidationChanged()**\n\n  当与row关联的验证错误改变时调用。\n\n* **onExpandInlineRow()**\n\n  内联row展开前调用。适用于遵循`InlineRowType`协议的rows。\n\n* **onCollapseInlineRow()**\n\n  内联row折叠前调用。适用于遵循`InlineRowType`协议的rows。\n\n* **onPresent()**\n\n\t在显示另外一个view controller之前调用。适用于遵循`PresenterRowType`的rows。可以在这里设置被显示的view controller。\n\n\n### Section Header和Footer <a name=\"section-header-footer\"></a>\n\n你可以将`String`的title或者自定义的`View`作为`Section`的header或者footer。\n\n#### String title\n```swift\nSection(\"Title\")\n\nSection(header: \"Title\", footer: \"Footer Title\")\n\nSection(footer: \"Footer Title\")\n```\n\n#### 自定义View\n你可以使用一个`.xib`作为自定义View：\n\n```swift\nSection() { section in\n    var header = HeaderFooterView<MyHeaderNibFile>(.nibFile(name: \"MyHeaderNibFile\", bundle: nil))\n\n    // header每次出现在屏幕的时候调用\n    header.onSetupView = { view, _ in\n        // 通常是在这修改view里面的文字\n        // 不要在这修改view的大小或者层级关系\n    }\n    section.header = header\n}\n```\n\n或者是一个使用纯代码创建的`UIView`\n\n```swift\nSection(){ section in\n    var header = HeaderFooterView<MyCustomUIView>(.class)\n    header.height = {100}\n    header.onSetupView = { view, _ in\n        view.backgroundColor = .red\n    }\n    section.header = header\n}\n```\n\n或者直接用callback来创建view\n\n```swift\nSection(){ section in\n    section.header = {\n          var header = HeaderFooterView<UIView>(.callback({\n              let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))\n              view.backgroundColor = .red\n              return view\n          }))\n          header.height = { 100 }\n          return header\n        }()\n}\n```\n\n### 动态地隐藏和显示row(或者Sections)  <a name=\"hide-show-rows\"></a>\n\n<img src=\"../Example/Media/EurekaSwitchSections.gif\" width=\"300\" alt=\"Screenshot of Hidden Rows\" />\n\n在这个例子里，我们隐藏或显示整个sections。\n\n为了达到这个效果，每个row有一个`Condition`的可选类型的变量`hidden`，`Condition`可以通过`function`或者`NSPredicate`来设置。\n\n\n#### 使用function condition来隐藏\n\n使用`Condition`的`function` case:\n```swift\nCondition.function([String], (Form)->Bool)\n```\n`function`需要一个`Form`参数，并返回`Bool`，决定当前row是否需要隐藏。这是一个非常强大的设置`hidden`的方式，因为它没有明显的限制。\n\n```swift\nform +++ Section()\n            <<< SwitchRow(\"switchRowTag\"){\n                $0.title = \"Show message\"\n            }\n            <<< LabelRow(){\n\n                $0.hidden = Condition.function([\"switchRowTag\"], { form in\n                    return !((form.rowBy(tag: \"switchRowTag\") as? SwitchRow)?.value ?? false)\n                })\n                $0.title = \"Switch is on!\"\n        }\n```\n\n<img src=\"../Example/Media/EurekaHidden.gif\" width=\"300\" alt=\"Screenshot of Hidden Rows\" />\n\n```swift\npublic enum Condition {\n    case function([String], (Form)->Bool)\n    case predicate(NSPredicate)\n}\n```\n\n#### 使用NSPredicate隐藏\n\n`hidden`也可以用NSPredicate来设置。在predicate string里面，你可以引用其他row的tags，然后决定一个row是否需要隐藏。\n\n但是使用NSPredicate来设置`hidden`的方式只适用于其他rows的value继承自NSObject（String 和 Int 也适用，因为它们被桥接到OjbC对应的类型，但是enums不适用）\n\n使用NSPredicate限制这么多，我们为什么要使用它呢？\n因为它比function更简单、更短而且更易读。例如下面这个例子：\n\n```swift\n$0.hidden = Condition.predicate(NSPredicate(format: \"$switchTag == false\"))\n```\n\n我们还可以写的更简单，因为`Condition`遵循`ExpressibleByStringLiteral`：\n\n```swift\n$0.hidden = \"$switchTag == false\"\n```\n\n*注意：我们会在执行的时候把'$switchTag'替换成tag为switchTag的row的value。*\n\n所以的rows都必须有一个tag，我们会用这个tag去找到对应的row，这样才能达到我们想要的效果。\n\n我们也可以直接隐藏一个row：\n```swift\n$0.hidden = true\n```\n因为`Condition`遵循`ExpressibleByBooleanLiteral`.\n\n如果不设置`hidden`变量，那么对应的rows就会一直显示。\n\n##### Sections\n\n对于section来说，也是一样的。我们也可以通过设置`hidden`属性来控制显示或隐藏。\n\n##### 禁用rows\n\n为了禁用rows，每个row有一个`disable`变量，也是`Condition`的可选类型。使用的方式跟`hidden`一样，所以要求每个row有一个tag。\n\nNote that if you want to disable a row permanently you can also set `disabled` variable to `true`.\n注意：如果你想永久的禁用一个row，可以把`disabled`设置为`true`.\n\n### 列表类型的sections\n\n为了显示一个列表选项，Eukera有一个特殊的section，叫做`SelectableSection`。\n\n当创建`SelectableSection`的时候，你需要传入在选项中使用的row的类型和`selectionTyle`。`selectionTyle`是一个枚举，`multipleSelection` 或者 `singleSelection(enableDeselection: Bool)`（`enableDeselection`决定选中的rows是否可以取消选中）。\n\n\n```swift\nform +++ SelectableSection<ListCheckRow<String>>(\"Where do you live\", selectionType: .singleSelection(enableDeselection: true))\n\nlet continents = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\nfor option in continents {\n    form.last! <<< ListCheckRow<String>(option){ listRow in\n        listRow.title = option\n        listRow.selectableValue = option\n        listRow.value = nil\n    }\n}\n```\n\n##### 可以使用什么类型的row？\n\n为了创建这样的section，你必须先创建一个遵循`SelectableRowType`协议的row。\n\n```swift\npublic protocol SelectableRowType : RowType {\n    var selectableValue : Value? { get set }\n}\n```\n\n`selectableValue`是row的value，将会被永久存储。而`value`变量将会用来决定row是否选中，如果被选中，它的值就等于`selectableValue`，否则为nil。Eureka包含上面例子用到的`ListCheckRow`，在自定义rows的实例程序中，你还可以找到`ImageCheckRow`。\n\n##### 获取选中的rows\n\n为了获得`SelectableSection`中被选中的row，Eukera提供了两个方法：`selectedRow()`（获取`SingleSelection`选中的row） and `selectedRows()`获取`MultipleSelection`所有选中的rows。\n\n##### 在sections中把选项分组\n\n另外，你可以使用`SelectorViewController`的属性把选项列表分组。\n\n- `sectionKeyForValue` - 是一个闭包，返回特定row的value对应的key，这个key被用来把选项分组。\n\n- `sectionHeaderTitleForKey` - 是一个闭包，返回特定key对应的section的header title，默认是key本身的值。\n\n- `sectionFooterTitleForKey` - 是一个闭包，返回特定key对应的section的footer title。\n\n### 有多个值的sections\n\nEureka可以通过有多个值的section来支持一个字段对应多个值的情况。它允许我们很容易地创建能插入的、能删除的和能排序的sections。\n\n<img src=\"../Example/Media/EurekaMultivalued.gif\" width=\"300\" alt=\"Screenshot of Multivalued Section\" />\n\n#### 如何创建多值section\n\n为了创建一个多值section，我们要使用`MultivaluedSection` ，而不是常规的`Section`。`MultivaluedSection`继承自`Section`，拥有一些额外的属性来设置多值section的行为。\n\n让我们来看一个例子：\n\n```swift\nform +++\n    MultivaluedSection(multivaluedOptions: [.Reorder, .Insert, .Delete],\n                       header: \"Multivalued TextField\",\n                       footer: \".Insert adds a 'Add Item' (Add New Tag) button row as last cell.\") {\n        $0.addButtonProvider = { section in\n            return ButtonRow(){\n                $0.title = \"Add New Tag\"\n            }\n        }\n        $0.multivaluedRowToInsertAt = { index in\n            return NameRow() {\n                $0.placeholder = \"Tag Name\"\n            }\n        }\n        $0 <<< NameRow() {\n            $0.placeholder = \"Tag Name\"\n        }\n    }\n```\n\n上面的代码演示了如何创建一个多值的section。在上面我们把insert, delete 和 reorder传给了`multivaluedOptions`。\n\n`addButtonProvider`允许我们自定义button row，当点击这个button row并且`multivaluedOptions`包含`.Insert`的时候，就会添加一行。\n\n`multivaluedRowToInsertAt`闭包在Eureka每次需要新的row插入的时候调用。为了提供一个row来插入到多值的section中，我们就要设置这个属性。Eureka传index作为闭包的参数。需要注意的是，我们可以返回任何类型的row，甚至自定义的row，即使在多数情况下多值section的rows都是同一类型的。\n\n当我们创建多值section的时候，Eureka会自动添加button row。我们刚刚说到我们可以自定义button row的外观。默认情况下button row的左边有一个加号按钮，我们可以通过设置`showInsertIconInAddButton`属性来决定是否要显示加号按钮。\n\n当创建一个可以插入的sections时，我们还需要更多的考虑。所以被添加到可插入的多值section的rows都应该放在Eureka通过点击按钮来插入的rows上面。我们可以在初始化section的时候，在最后一个闭包参数里添加额外的row，这样在点击button row的时候就会自动把要插入的rows放在最后面。\n\n#### 编辑模式\n\n默认情况下，Eureka只会在当表格中有含有MultivaluedSection的时候把tableView的`isEditing`设置为`true`，而且会在表格第一次显示时的`viewWillAppear`完成。\n\n要了解更多如何使用多值section的相关信息，可以看下Eureka的示例程序，里面包含了多种用法。\n\n### 验证\n\nEureka 2.0.0 内置了很多验证特性。\n\n一个row有很多规则和一个用于决定rules是否需要验证的特定配置。\n\n有很多规则是默认提供的，但是你也可以自己创建自己的规则。\n\n默认提供的规则:\n* RuleRequired\n* RuleEmail\n* RuleURL\n* RuleGreaterThan, RuleGreaterOrEqualThan, RuleSmallerThan, RuleSmallerOrEqualThan\n* RuleMinLength, RuleMaxLength\n* RuleClosure\n\n让我们看看如何设置验证规则。\n\n```swift\n\noverride func viewDidLoad() {\n        super.viewDidLoad()\n        form\n          +++ Section(header: \"Required Rule\", footer: \"Options: Validates on change\")\n\n            <<< TextRow() {\n                $0.title = \"Required Rule\"\n                $0.add(rule: RuleRequired())\n\n\t\t// 这也可以通过一个闭包来实现：如果验证通过，返回nil，否则返回一个ValidationError。\n\t\t/*\n\t\tlet ruleRequiredViaClosure = RuleClosure<String> { rowValue in\n\t\treturn (rowValue == nil || rowValue!.isEmpty) ? ValidationError(msg: \"Field required!\") : nil\n\t\t}\n\t\t$0.add(rule: ruleRequiredViaClosure)\n\t\t*/\n\n                $0.validationOptions = .validatesOnChange\n            }\n            .cellUpdate { cell, row in\n                if !row.isValid {\n                    cell.titleLabel?.textColor = .red\n                }\n            }\n\n          +++ Section(header: \"Email Rule, Required Rule\", footer: \"Options: Validates on change after blurred\")\n\n            <<< TextRow() {\n                $0.title = \"Email Rule\"\n                $0.add(rule: RuleRequired())\n                $0.add(rule: RuleEmail())\n                $0.validationOptions = .validatesOnChangeAfterBlurred\n            }\n            .cellUpdate { cell, row in\n                if !row.isValid {\n                    cell.titleLabel?.textColor = .red\n                }\n            }\n\n```\n\n从上面的代码可以看到，我们可以通过 `add(rule:)`设置多个我们想要的规则。\n\nRow还提供了`func remove(ruleWithIdentifier identifier: String)`来移除规则。为了使用这个方法，我们必须在创建规则的时候，给规则设置一个id。\n\n有时候我们想要在这个row上使用的规则，跟其他rows是一样的。这种情况下，我们可以使用`RuleSet`来设置所以规则：\n\n```swift\nvar rules = RuleSet<String>()\nrules.add(rule: RuleRequired())\nrules.add(rule: RuleEmail())\n\nlet row = TextRow() {\n            $0.title = \"Email Rule\"\n            $0.add(ruleSet: rules)\n            $0.validationOptions = .validatesOnChangeAfterBlurred\n        }\n```\n\nEureka允许我们指定何时执行验证规则。我们可以通过row的`validationOptions`属性来设置，它有以下这些值：\n\n* `.validatesOnChange` - 当row的value改变时执行。\n* `.validatesOnBlur` - （默认值）当cell辞去第一响应者时执行，不适用于所有rows。\n* `.validatesOnChangeAfterBlurred` - 在第一次辞去第一响应者之后，row的value改变时执行\n* `.validatesOnDemand` - 我们需要手动调用`validate()`来验证row或者form\n\n如果你想验证整个form（或者所有rows），你可以手动调用Form的`validate()`方法。\n\n#### 如何获取验证错误\n\n每个row都有一个`validationErrors`属性，可以用来获取所有验证错误。这个属性仅仅存储了最后一次验证的错误清单，并不会执行验证规则。\n\n#### 注意类型\n\n正如我们所想的那样，规则的类型必须与row的类型相同。要格外小心检查所使用的row类型。你可能会看到这个编译错误：`\"(Incorrect arugment label in call (have 'rule:' expected 'ruleSet:')\"`，这并不是把类型混淆了的问题。\n\n### 滑动操作\n\nEureka 4.1.0 引入了滑动特性.\n\n现在你可以为每一行定义多个`leadingSwipe` 和 `trailingSwipe`操作。因为滑动操作决定于iOS系统的特性，所以`leadingSwipe`只能用于iOS 11 以上的系统。\n\n让我们看看如何定义滑动操作：\n\n```swift\nlet row = TextRow() {\n            let deleteAction = SwipeAction(\n                style: .destructive,\n                title: \"Delete\",\n                handler: { (action, row, completionHandler) in\n                    // 在这添加你的代码\n                    // 操作完成后一定要调用completionHandler\n                    completionHandler?(true)\n                })\n            deleteAction.image = UIImage(named: \"icon-trash\")\n\n            $0.trailingSwipe.actions = [deleteAction]\n            $0.trailingSwipe.performsFirstActionWithFullSwipe = true\n\n            // 请注意：`leadingSwipe`只能用于iOS 11以上的系统\n            let infoAction = SwipeAction(\n                style: .normal,\n                title: \"Info\",\n                handler: { (action, row, completionHandler) in\n                    // 在这添加你的代码\n                    // 操作完成后一定要调用completionHandler\n                    completionHandler?(true)\n                })\n            infoAction.backgroundColor = .blue\n            infoAction.image = UIImage(named: \"icon-info\")\n\n            $0.leadingSwipe.actions = [infoAction]\n            $0.leadingSwipe.performsFirstActionWithFullSwipe = true\n        }\n```\n\n滑动操作需要把`tableView.isEditing`设置为`false`。Eureka会在当表格中有含有MultivaluedSection的时候把tableView的`isEditing`设置为`true`（在`viewWillAppear`设置）。如果你在同一个表格中同时拥有MultivaluedSections和滑动操作，你要根据情况来设置`isEditing`。\n\n## 自定义row\n\n通常你需要自定义不同于Eureka内置的row。这其实不是很难，你可以阅读[如何自定义rows的教程](https://blog.xmartlabs.com/2016/09/06/Eureka-custom-row-tutorial/)来开始。你也可以看看[EurekaCommunity]，这里包含了其他rows，并准备加入到Eukera中。\n\n### 简单的自定义rows\n\n为了创建一个拥有自定义行为和外观的row，你可能需要继承于`Row`和`Cell`。\n\n请记住`Row`是Eureka使用的抽象类；而`Cell`实际上是`UITableViewCell`，用于管理view。\n因为`Row`包含了`Cell`，所以`Row`和`Cell`必须同时定义。\n\n```swift\n// 自定义value类型是Bool的Cell\n// Cell是使用 .xib 定义的，所以我们可以直接设置outlets\npublic class CustomCell: Cell<Bool>, CellType {\n    @IBOutlet weak var switchControl: UISwitch!\n    @IBOutlet weak var label: UILabel!\n\n    public override func setup() {\n        super.setup()\n        switchControl.addTarget(self, action: #selector(CustomCell.switchValueChanged), for: .valueChanged)\n    }\n\n    func switchValueChanged(){\n        row.value = switchControl.on\n        row.updateCell() // Re-draws the cell which calls 'update' bellow\n    }\n\n    public override func update() {\n        super.update()\n        backgroundColor = (row.value ?? false) ? .white : .black\n    }\n}\n\n// 自定义的Row，拥有CustomCell和对应的value\npublic final class CustomRow: Row<CustomCell>, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        // 我们把对应CustomCell的 .xib 加载到cellProvidor\n        cellProvider = CellProvider<CustomCell>(nibName: \"CustomCell\")\n    }\n}\n```\n结果: <br>\n<img src=\"../Example/Media/EurekaCustomRow.gif\" alt=\"Screenshot of Disabled Row\"/>\n\n<br>\n\n自定义rows需要继承自 `Row<CellType>`，并遵循`RowType`协议。\n自定义的cells必须继承自`Cell<ValueType>`，并遵循`CellType`协议。\n\n就像cellSetup和CellUpdate回调一样，`Cell`有setup和update方法，你可以在里面做自定义。\n\n\n### 自定义内联rows\n\n内联row是一个特定的row类型，可以在它下面动态的显示一个row。正常来说内联row在被点击时在展开和折叠两种状态切换。\n\n所以，为了创建一个内联row，我们需要两个rows，一个总是显示的row，另外一个被展开和折叠的row。\n\n另外一个要求是，这两个rows的value类型必须是一样的。\n\n一旦我们拥有了两个rows，我们要让第一个row遵循`InlineRowType`，这将会给第一个row添加一些方法：\n\n```swift\nfunc expandInlineRow()\nfunc hideInlineRow()\nfunc toggleInlineRow()\n```\n\n最后，当row被点击时我们要调用`toggleInlineRow()`，例如重写`customDidSelect()`方法：\n\n```swift\npublic override func customDidSelect() {\n    toggleInlineRow()\n}\n```\n\n### 自定义Presenter rows <a name=\"presenter-rows\"></a>\n\n**注意:** *一个Presenter row 是可以弹出UIViewController的row。*\n\n为了创建一个Presenter rows，必须创建一个遵循`PresenterRowType`的类。高度推荐继承自`SelectorRow`，因为它遵循了那个协议并且添加了其他很有用的方法。\n\n`PresenterRowType`协议的定义如下:\n```swift\npublic protocol PresenterRowType: TypedRowType {\n    typealias ProviderType : UIViewController, TypedRowControllerType\n    var presentationMode: PresentationMode<ProviderType>? { get set }\n    var onPresentCallback: ((FormViewController, ProviderType)->())? { get set }\n}\n```\n\n`onPresentCallback`将会在row即将显示另外一个view controller的时候调用。在`SelectorRow`里面已经调用了，如果你没有继承自它的话，你需要自己手动调用。\n\n`presentationMode`定义了应该显示哪个controller和怎么显示controller。我们可以通过Segue identifier、segue class、present或者push来展示controller。例如一个CustomPushRow可以像这样定义：\n\n```swift\npublic final class CustomPushRow<T: Equatable>: SelectorRow<PushSelectorCell<T>, SelectorViewController<T>>, RowType {\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        presentationMode = .show(controllerProvider: ControllerProvider.callback {\n            return SelectorViewController<T>(){ _ in }\n            }, onDismiss: { vc in\n                _ = vc.navigationController?.popViewController(animated: true)\n        })\n    }\n}\n```\n\n你可以用自己的UIViewController替换`SelectorViewController<T>`，用自己的cell替换`PushSelectorCell<T>`。\n\n### 使用相同的row来子类化cells\n\n有时候我们想要改变我们其中一个row的外观，但是不需要改变row的类型和已有的逻辑。如果我们使用的cell是通过`xib`文件来初始化的，那么现在有一种方法能达到我们的要求。目前，所有Eureka内置的rows都不是通过`xib`来初始化的，但是[EurekaCommunity]的一些自定义rows是通过`xib`初始化，例如[PostalAddressRow](https://github.com/EurekaCommunity/PostalAddressRow)。\n\n你所需要做的是：\n\n* 创建一个包含你想要创建的cell的nib文件。\n* 然后把cell的class设置为你想要修改的cell（如果你想要更改除了UI以外的东西，你需要子类化那个cell。），并且确保那个cell的module是正确的。\n* 把outlets连接到类中\n* 告诉你的row使用这个新的nib文件。这是通过设置`cellProvider`来完成的，这个设置需要在具体的初始化过程或者`defaultRowInitializer`里面完成。例如：\n\n```swift\n<<< PostalAddressRow() {\n     $0.cellProvider = CellProvider<PostalAddressCell>(nibName: \"CustomNib\", bundle: Bundle.main)\n}\n```\n\n另外，你也可以创建一个新的row来达到目的。这种情况下你要继承同一个父类，让这个row继承它的逻辑。\n\n当我们在实现这个的时候，有些东西可以考虑下：\n\n* 如果你想要看例子，你可以看看[PostalAddressRow](https://github.com/EurekaCommunity/PostalAddressRow)或者[CreditCardRow](https://github.com/EurekaCommunity/CreditCardRow)，它们都是用了自定义的nib文件。\n* 如果你遇到了这样的错误：`Unknown class <YOUR_CLASS_NAME> in Interface Builder file`，可能是你需要在代码中的某个位置、在运行的时候实例化那个新的类型。我是通过调用`let t = YourClass.self`来解决的。\n\n\n\n\n## row目录\n\n### Controls Rows\n<table>\n    <tr>\n        <td><center><b>Label Row</b><br>\n        <img src=\"../Example/Media/RowStatics/LabelRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Button Row</b><br>\n        <img src=\"../Example/Media/RowStatics/ButtonRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Check Row</b><br>\n        <img src=\"../Example/Media/RowStatics/CheckRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n    <tr>\n        <td><center><b>Switch Row</b><br>\n        <img src=\"../Example/Media/RowStatics/SwitchRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Slider Row</b><br>\n        <img src=\"../Example/Media/RowStatics/SliderRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Stepper Row</b><br>\n        <img src=\"../Example/Media/RowStatics/StepperRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n    <tr>\n        <td><center><b>Text Area Row</b><br>\n        <img src=\"../Example/Media/RowStatics/TextAreaRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n</table>\n\n### Field Rows\n\n这些rows在cell的右边有一个textField，它们的不同之处在于包含不同的大小写、自动更正和键盘类型配置。\n\n<table>\n<tr>\n  <td>\n    <img src=\"../Example/Media/CatalogFieldRows.jpg\" width=\"300\"/>\n  </td>\n  <td>\n  TextRow<br><br>\n  NameRow<br><br>\n  URLRow<br><br>\n  IntRow<br><br>\n  PhoneRow<br><br>\n  PasswordRow<br><br>\n  EmailRow<br><br>\n  DecimalRow<br><br>\n  TwitterRow<br><br>\n  AccountRow<br><br>\n  ZipCodeRow\n  </td>\n<tr>\n</table>\n\n上面所有的`FieldRow`类型都有一个<a href=\"https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFormatter_Class/\">`NSFormatter`</a>类型的`formatter`属性，可以用来控制row的value如何显示。Eureka内置了一个可以保留两位小数的formatter，`DecimalFormatter`。实例程序中包含了`CurrencyFormatter`，可以根据用户所在地显示相应的货币格式。\n\n默认情况下，设置row的`formatter`只会影响到在没有被编辑的时候的显示格式。如果要在编辑的时候也要格式化，要在初始化row的时候把`useFormatterDuringInput`设置为`true`。编辑的时候格式化value的时候可能需要更新光标的位置，Eukera提供了下面的协议，你的formatter需要遵循这个协议来处理光标的位置：\n\n```swift\npublic protocol FormatterProtocol {\n    func getNewPosition(forPosition forPosition: UITextPosition, inTextInput textInput: UITextInput, oldValue: String?, newValue: String?) -> UITextPosition\n}\n```\n\n另外，`FieldRow`有一个`useFormatterOnDidBeginEditing`属性。当使用`DecimalRow`的时候，并且有一个允许decimal value和遵循用户所在地的formatter，例如`DecimalFormatter`，如果`useFormatterDuringInput`是`false`，`useFormatterOnDidBeginEditing`必须设置为`true`，这样value中的小数点才能匹配键盘中的小数点。\n\n### Date Rows\n\nDate Rows存储了一个Date，并且允许我们通过UIDatePicker来设置一个新的值。UIDatePicker的模式和date picker view的显示方法如下图：\n\n<table>\n<tr>\n<td>\n<center><b>Date Row</b>\n<img src=\"../Example/Media/RowGifs/EurekaDateRow.gif\" height=\"220\" width=\"230\" />\n<br>\nPicker在键盘上显示\n</center>\n</td>\n<td>\n<center><b>Date Row (Inline)</b>\n<img src=\"../Example/Media/RowGifs/EurekaDateInlineRow.gif\" height=\"220\" width=\"210\"/>\n<br>\nrow展开\n</center>\n</td>\n<td>\n<center><b>Date Row (Picker)</b>\n<img src=\"../Example/Media/RowGifs/EurekaDatePickerRow.gif\" height=\"220\" width=\"210\"/>\n<br>\npicker一直显示\n</center>\n</td>\n</tr>\n</table>\n\n有三种风格（Normal、Inline和Picker），Eureka还包括：\n\n+ **DateRow**\n+ **TimeRow**\n+ **DateTimeRow**\n+ **CountDownRow**\n\n### Option Rows\n\nOption Rows关联着用户必须选择的一系列选项。\n\n```swift\n<<< ActionSheetRow<String>() {\n                $0.title = \"ActionSheetRow\"\n                $0.selectorTitle = \"Pick a number\"\n                $0.options = [\"One\",\"Two\",\"Three\"]\n                $0.value = \"Two\"    // initially selected\n            }\n```\n\n<table>\n<tr>\n<td width=\"25%\">\n<center><b>Alert Row</b><br>\n<img src=\"../Example/Media/RowStatics/AlertRow.jpeg\"/>\n<br>\n通过Alert的方式显示。\n</center>\n</td>\n<td width=\"25%\">\n<center><b>ActionSheet Row</b><br>\n<img src=\"../Example/Media/RowStatics/ActionSheetRow.jpeg\"/>\n<br>\n通过action sheet的方式显示。\n</center>\n</td>\n<td width=\"25%\">\n<center><b>Push Row</b><br>\n<img src=\"../Example/Media/RowStatics/PushRow.jpeg\"/>\n<br>\npush到一个新的controller。\n</center>\n</td>\n<td width=\"25%\">\n<center><b>Multiple Selector Row</b><br>\n<img src=\"../Example/Media/RowStatics/MultipleSelectorRow.jpeg\"/>\n<br>\n像PushRow一样，但是允许多选。\n</center>\n</td>\n</tr>\n</table>\n\n<table>\n    <tr>\n        <td><center><b>Segmented Row</b><br>\n        <img src=\"../Example/Media/RowStatics/SegmentedRow.png\"/>\n        </center>\n        </td>\n        <td><center><b>Segmented Row (w/Title)</b><br>\n        <img src=\"../Example/Media/RowStatics/SegmentedRowWithTitle.png\"/>\n        </center>\n        </td>\n        <td><center><b>Picker Row</b><br>\n        <img src=\"../Example/Media/RowStatics/PickerRow.png\"/>\n        <br>通过picker view来显示通用类型选项\n        <br><b>(也有Picker内联Row)</b>\n        </center>\n        </td>\n    </tr>\n</table>\n\n### 建立自己的自定义row?\n让我们知道它，我们会跟高兴的在这提到它。:)\n\n* **LocationRow** (在示例程序中作为自定义row)\n\n<img src=\"../Example/Media/EurekaLocationRow.gif\" width=\"300\" alt=\"Screenshot of Location Row\"/>\n\n## 安装\n\n#### CocoaPods\n\n[CocoaPods](https://cocoapods.org/) 是一个管理Cocoa项目的依赖。\n\n在项目中的`Podfile`文件指定Eureka:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '9.0'\nuse_frameworks!\n\npod 'Eureka'\n```\n\n然后运行下面的命令:\n\n```bash\n$ pod install\n```\n\n#### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) 是一个简单的、分散的Cocoa依赖管理器。\n\n在项目中的`Cartfile`文件文件指定Eureka:\n\n```ogdl\ngithub \"xmartlabs/Eureka\" ~> 4.0\n```\n\n#### 手动集成框架\n\n* 在项目的根目录运行下列代码克隆Eureka，作为一个git [submodule](http://git-scm.com/docs/git-submodule)。\n\n```bash\n$ git submodule add https://github.com/xmartlabs/Eureka.git\n```\n\n* 克隆完成后，打开Eureka文件夹，然后把`Eureka.xcodeproj`拖动到Xcode项目的Project Navigator中\n\n* 在Project Navigator选中`Eureka.xcodeproj`，检查deployment target是否跟应用的匹配\n\n* 在Project Navigator选中你自己的项目，选择自己应用的target，然后选择在\"General\"选项卡，在`Embedded Binaries`点击加号\n\n* 选择`Eureka.framework`，大功告成。\n\n## 参与其中\n\n* 如果你想贡献，请随时提交pull request。\n* 如果你有新功能要求，请开一个issue。\n* 如果你找到了一个bug，在提交新的issue之前，请先查看旧的issues。\n* 如果你需要帮助，或者询问常见的问题，使用[StackOverflow]。（Tag `eureka-forms`）\n\n**在贡献之前，请先查看[CONTRIBUTING](../CONTRIBUTING.md)文件了解更多信息。**\n\n如果你在你的项目中使用了**Eureka**，我们很想听到这个消息。可以在[twitter]给我发消息。\n\n## 作者\n\n* [Martin Barreto](https://github.com/mtnBarreto) ([@mtnBarreto](https://twitter.com/mtnBarreto))\n* [Mathias Claassen](https://github.com/mats-claassen) ([@mClaassen26](https://twitter.com/mClaassen26))\n\n## 常见问题解答\n\n#### 如果通过tag获取Row\n\n我们可以通过调用`Form`暴露的下列方法来获取特定的row：\n\n```swift\npublic func rowBy<T: Equatable>(tag: String) -> RowOf<T>?\npublic func rowBy<Row: RowType>(tag: String) -> Row?\npublic func rowBy(tag: String) -> BaseRow?\n```\n\n例如:\n\n```swift\nlet dateRow : DateRow? = form.rowBy(tag: \"dateRowTag\")\nlet labelRow: LabelRow? = form.rowBy(tag: \"labelRowTag\")\n\nlet dateRow2: Row<DateCell>? = form.rowBy(tag: \"dateRowTag\")\n\nlet labelRow2: BaseRow? = form.rowBy(tag: \"labelRowTag\")\n```\n\n#### 如果使用tag获取Section\n\n```swift\nlet section: Section?  = form.sectionBy(tag: \"sectionTag\")\n```\n\n#### 如果使用dictionary来设置form的值\n\n调用`Form`暴露的`setValues(values: [String: Any?])`方法.\n\n例如:\n\n```swift\nform.setValues([\"IntRowTag\": 8, \"TextRowTag\": \"Hello world!\", \"PushRowTag\": Company(name:\"Xmartlabs\")])\n```\n\n`\"IntRowTag\"`、 `\"TextRowTag\"`、 `\"PushRowTag\"` 是row tag (每个都唯一地标识一个row)， `8`、 `\"Hello world!\"`、 `Company(name:\"Xmartlabs\")` 是对应的要赋给row的值。\n\nrow的value类型必须匹配dictionary中对应值的类型，否则会将nil赋给row的value。\n\n如果form已经显示了，我们必须刷新已经显示的rows，可以通过调用`tableView.reloadData()`来刷新table view，或者调用已经显示的row的`updateCell()`方法。\n\n#### 更改hidden或者disable condition后，Row没有更新\n\n在设置了一个condition之后，这个condition不会自动执行，如果你想要马上执行，你可以调用`.evaluateHidden()` 或者 `.evaluateDisabled()`。\n\n这些方法仅仅在row被添加到form时和row改变时调用。如果这个condition被更改了，但是这个row处于显示状态，必须手动执行。\n\n#### 除非onCellHighlight也被定义了，否则onCellUnHighlight不会被调用\n\n查看这个[issue](https://github.com/xmartlabs/Eureka/issues/96).\n\n#### 如更新 Section header/footer\n\n* 设置新的 header/footer ....\n\n```swift\nsection.header = HeaderFooterView(title: \"Header title \\(variable)\") // 使用 String interpolation\n//或者\nvar header = HeaderFooterView<UIView>(.class) // 使用任何view类型更灵活地设置header\nheader.height = { 60 }  // 可以指高度\nheader.onSetupView = { view, section in  // 每次view即将显示时，onSetupView被调用\n    view.backgroundColor = .orange\n}\nsection.header = header\n```\n\n* 刷新Section\n\n```swift\nsection.reload()\n```\n\n#### 如何自定义Selector 和 MultipleSelector 选项的cells\n\n`selectableRowSetup`、`selectableRowCellUpdate` 和 `selectableRowCellSetup` 可以自定义 SelectorViewController 和 MultipleSelectorViewController的可选cells.\n\n```swift\nlet row = PushRow<Emoji>() {\n              $0.title = \"PushRow\"\n              $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n              $0.value = 👦🏼\n              $0.selectorTitle = \"Choose an Emoji!\"\n          }.onPresent { from, to in\n              to.dismissOnSelection = false\n              to.dismissOnChange = false\n              to.selectableRowSetup = { row in\n                  row.cellProvider = CellProvider<ListCheckCell<Emoji>>(nibName: \"EmojiCell\", bundle: Bundle.main)\n              }\n              to.selectableRowCellUpdate = { cell, row in\n                  cell.textLabel?.text = \"Text \" + row.selectableValue!  // 自定义\n                  cell.detailTextLabel?.text = \"Detail \" +  row.selectableValue!\n              }\n          }\n\n```\n\n#### 不想使用Eureka提供的自定义操作符？\n\n正如我们所说的，`Form`和`Section`遵循`MutableCollection`和`RangeReplaceableCollection`。一个Form是一个Sections的集合，一个Sections是一个Rows的集合。\n\n`RangeReplaceableCollection` 协议扩展提供了很多方法来改变集合。\n\n```swift\nextension RangeReplaceableCollection {\n    public mutating func append(_ newElement: Self.Element)\n    public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element\n    public mutating func insert(_ newElement: Self.Element, at i: Self.Index)\n    public mutating func insert<S>(contentsOf newElements: S, at i: Self.Index) where S : Collection, Self.Element == S.Element\n    public mutating func remove(at i: Self.Index) -> Self.Element\n    public mutating func removeSubrange(_ bounds: Range<Self.Index>)\n    public mutating func removeFirst(_ n: Int)\n    public mutating func removeFirst() -> Self.Element\n    public mutating func removeAll(keepingCapacity keepCapacity: Bool)\n    public mutating func reserveCapacity(_ n: Self.IndexDistance)\n}\n```\n\n上面的方法在内部用来实现自定义的操作：\n\n```swift\npublic func +++(left: Form, right: Section) -> Form {\n    left.append(right)\n    return left\n}\n\npublic func +=<C : Collection>(inout lhs: Form, rhs: C) where C.Element == Section {\n    lhs.append(contentsOf: rhs)\n}\n\npublic func <<<(left: Section, right: BaseRow) -> Section {\n    left.append(right)\n    return left\n}\n\npublic func +=<C : Collection>(inout lhs: Section, rhs: C) where C.Element == BaseRow {\n    lhs.append(contentsOf: rhs)\n}\n```\n\n你可以在[这里](https://github.com/xmartlabs/Eureka/blob/master/Source/Core/Operators.swift)看到剩下的自定义操作符是如何实现的。\n\n是否要用自定义的操作符，完全由你自己决定。\n\n<!--- In file -->\n[要求]: #要求\n\n[使用]: #使用\n[如何创建表格]: #如何创建表格\n[获取行的值]: #获取行的值\n[操作符]: #操作符\n[callbacks的使用]: #callbacks的使用\n[Section Header和Footer]: #section-header-footer\n[动态地隐藏和显示row(或者Sections)]: #hide-show-rows\n[列表类型的sections]: #列表类型的sections\n[有多个值的sections]: #有多个值的sections\n[验证]: #验证\n[滑动操作]: #滑动操作\n\n[自定义row]: #自定义row\n[简单的自定义rows]: #简单的自定义rows\n[自定义内联rows]: #自定义内联rows\n[自定义Presenter rows]: #presenter-rows\n[row目录]: #row目录\n\n[安装]: #安装\n[常见问题解答]: #常见问题解答\n\n\n<!--- In Project -->\n[CustomCellsController]: ../Example/Example/ViewController.swift\n[FormViewController]: ../Example/Source/Controllers.swift\n\n<!--- External -->\n[XLForm]: https://github.com/xmartlabs/XLForm\n[DSL]: https://en.wikipedia.org/wiki/Domain-specific_language\n[StackOverflow]: http://stackoverflow.com/questions/tagged/eureka-forms\n[our blog post]: http://blog.xmartlabs.com/2015/09/29/Introducing-Eureka-iOS-form-library-written-in-pure-Swift/\n[twitter]: https://twitter.com/xmartlabs\n[EurekaCommunity]: https://github.com/EurekaCommunity\n\n# 捐赠Eureka\n\n所以我们可以让Eureka变得更好！<br><br>\n[<img src=\"../donate.png\"/>](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HRMAH7WZ4QQ8E)\n\n# 更改日志\n\n可以在[CHANGELOG.md](../CHANGELOG.md)文件中查看。\n"
  },
  {
    "path": "Eureka.playground/Contents.swift",
    "content": "//: **Eureka Playground** - let us walk you through Eureka! cool features, we will show how to\n//: easily create powerful forms using Eureka!\n\n//: It allows us to create complex dynamic table view forms and obviously simple static table view. It's ideal for data entry task or settings pages.\n\nimport UIKit\nimport XCPlayground\nimport PlaygroundSupport\n\n//: Start by importing Eureka module\nimport Eureka\n\n//: Any **Eureka** form must extend from `FormViewController`\nlet formController = FormViewController()\nPlaygroundPage.current.liveView = formController.view\n\nlet b = [Int]()\nb.last\n\nlet f = Form()\nf.last\n\n//: ## Operators\n//: ### +++\n//: Adds a Section to a Form when the left operator is a Form\nlet form = Form() +++ Section()\n//: When both operators are a Section it creates a new Form containing both Section and return the created form.\nlet form2 = Section(\"First\") +++ Section(\"Second\") +++ Section(\"Third\")\n//: Notice that you don't need to add parenthesis in the above expresion, +++ operator is left associative so it will create a form containing the 2 first sections and then append last Section (Third) to the created form.\n//: form and form2 don't have any row and are not useful at all. Let's add some rows.\n\n//: ### +++ \n//: Can be used to append a row to a form without having to create a Section to contain the row. The form section is implicitly created as a result of the +++ operator.\nformController.form +++ TextRow(\"Text\")\n//: it can also be used to append a Section like this:\nformController.form +++ Section()\n\n//: ### <<<\n//: Can be used to append rows to a section.\nformController.form.last! <<< SwitchRow(\"Switch\") { $0.title = \"Switch\"; $0.value = true }\n\n//: it can also be used to create a section and append rows to it. Let's use that to add a new section to the form\nformController.form +++ PhoneRow(\"Phone\") { $0.title = \"Phone\"}\n                        <<< IntRow(\"IntRow\") { $0.title = \"Int\"; $0.value = 5 }\n\nformController.view\n//: # Callbacks\n//: Rows might have several closures associated to be called at different events. Let's see them one by one. Sadly, we can not interact with it in our playground.\n\n//: ### onChange callback\n//: Will be called when the value of a row changes. Lots of things can be done with this feature. Let's create a new section for the new rows:\nformController.form +++ Section(\"Callbacks\") <<< SwitchRow(\"scr1\") { $0.title = \"Switch to turn red\"; $0.value = false }\n    .onChange({ row in\n        if row.value == true {\n            row.cell.backgroundColor = .red\n        } else {\n            row.cell.backgroundColor = .black\n        }\n    })\n\n//: Now when we change the value of this row its background color will change to red. Try that by (un)commenting the following line:\nformController.view\nformController.form.last?.last?.baseValue = true\nformController.view\n//: Notice that we set the `baseValue` attribute because we did not downcast the result of `formController.form.last?.last`. It is essentially the same as the `value` attribute\n\n//: ### cellSetup and cellUpdate callbacks\n//: The cellSetup will be called when the cell of this row is configured (just once at the beginning)\n//: and the cellUpdate will be called when it is updated (each time it reappears on screen). Here you should define the appearance of the cell\n\nformController.form.last! <<< SegmentedRow<String>(\"Segments\") { $0.title = \"Choose an animal\"; $0.value = \"🐼\"; $0.options = [\"🐼\", \"🐶\", \"🐻\"]}.cellSetup({ cell, _ in\n        cell.backgroundColor = .red\n}).cellUpdate({ (cell, _) -> Void in\n    cell.textLabel?.textColor = .yellow\n})\n\n//: ### onSelection and onPresent callbacks\n//: OnSelection will be called when this row is selected (tapped by the user). It might be useful for certain rows instead of the onChange callback.\n//: OnPresent will be called when a row that presents another view controller is tapped. It might be useful to set up the presented view controller.\n//: We can not try them out in the playground but they can be set just like the others.\n\nformController.form.last! <<< SegmentedRow<String>(\"Segments2\") { $0.title = \"Choose an animal\"; $0.value = \"🐼\"; $0.options = [\"🐼\", \"🐶\", \"🐻\"]\n}.onCellSelection { cell, row in\n    print(\"\\(cell) for \\(row) got selected\")\n}\n\nformController.view\n\n//: ### Hiding rows\n//: We can hide rows by defining conditions that will tell if they should appear on screen or not. Let's create a row that will hide when the previous one is \"🐼\".\n\nformController.form.last! <<< LabelRow(\"Confirm\") {\n    $0.title = \"Are you sure you do not want the 🐼?\"\n    $0.hidden = \"$Segments2 == '🐼'\"\n}\n\n//: Now let's see how this works:\n\nformController.view\nformController.form.rowBy(tag: \"Segments2\")?.baseValue = \"🐶\"\nformController.view\n\n//: We can do the same using functions. Functions are specially useful for more complicated conditions. \n//: This applies when the value of the row we depend on is not compatible with NSPredicates (which is not the current case, but anyway).\n\nformController.form.last! <<< LabelRow(\"Confirm2\") {\n    $0.title = \"Well chosen!!\"\n    $0.hidden = Condition.function([\"Segments2\"]) { form in\n        if let r: SegmentedRow<String> = form.rowBy(tag: \"Segments2\") {\n            return r.value != \"🐼\"\n        }\n        return true\n    }\n}\n\n//: Now let's see how this works:\n\nformController.view\nformController.form.rowBy(tag: \"Segments2\")?.baseValue = \"🐼\"\nformController.view\n"
  },
  {
    "path": "Eureka.playground/contents.xcplayground",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<playground version='5.0' target-platform='ios' auto-termination-delay='20' display-mode='rendered' timelineScrubberEnabled='true' last-migration='1020'>\n    <timeline fileName='timeline.xctimeline'/>\n</playground>"
  },
  {
    "path": "Eureka.playground/playground.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Eureka.playground/playground.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Eureka.playground/timeline.xctimeline",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Timeline\n   version = \"3.0\">\n   <TimelineItems>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=734&amp;EndingColumnNumber=19&amp;EndingLineNumber=26&amp;StartingColumnNumber=0&amp;StartingLineNumber=26&amp;Timestamp=575824644.159923\"\n         lockedSize = \"{1063, 340}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1253&amp;EndingColumnNumber=31&amp;EndingLineNumber=32&amp;StartingColumnNumber=12&amp;StartingLineNumber=32&amp;Timestamp=575824644.160043\"\n         lockedSize = \"{322, 325}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=9&amp;CharacterRangeLoc=1567&amp;EndingColumnNumber=24&amp;EndingLineNumber=38&amp;StartingColumnNumber=15&amp;StartingLineNumber=38&amp;Timestamp=575824644.160136\"\n         lockedSize = \"{328, 416}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1373&amp;EndingColumnNumber=151&amp;EndingLineNumber=32&amp;StartingColumnNumber=132&amp;StartingLineNumber=32&amp;Timestamp=575824644.160224\"\n         lockedSize = \"{395, 526}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=0&amp;CharacterRangeLoc=3649&amp;EndingColumnNumber=12&amp;EndingLineNumber=77&amp;StartingColumnNumber=12&amp;StartingLineNumber=77&amp;Timestamp=575824644.160311\"\n         lockedSize = \"{354, 450}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=90&amp;CharacterRangeLoc=1598&amp;EndingColumnNumber=0&amp;EndingLineNumber=40&amp;StartingColumnNumber=1&amp;StartingLineNumber=39&amp;Timestamp=575824644.160396\"\n         lockedSize = \"{453, 531}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=0&amp;CharacterRangeLoc=152&amp;EndingColumnNumber=9&amp;EndingLineNumber=3&amp;StartingColumnNumber=9&amp;StartingLineNumber=3&amp;Timestamp=575824644.160482\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=0&amp;CharacterRangeLoc=1641&amp;EndingColumnNumber=44&amp;EndingLineNumber=39&amp;StartingColumnNumber=44&amp;StartingLineNumber=39&amp;Timestamp=575824644.160576\"\n         lockedSize = \"{566, 773}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=988&amp;EndingColumnNumber=88&amp;EndingLineNumber=28&amp;StartingColumnNumber=69&amp;StartingLineNumber=28&amp;Timestamp=575824644.160663\"\n         lockedSize = \"{177, 169}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1621&amp;EndingColumnNumber=43&amp;EndingLineNumber=39&amp;StartingColumnNumber=24&amp;StartingLineNumber=39&amp;Timestamp=575824644.160761\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1057&amp;EndingColumnNumber=157&amp;EndingLineNumber=28&amp;StartingColumnNumber=138&amp;StartingLineNumber=28&amp;Timestamp=575824644.1608551\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=2259&amp;EndingColumnNumber=103&amp;EndingLineNumber=50&amp;StartingColumnNumber=84&amp;StartingLineNumber=50&amp;Timestamp=575824644.160948\"\n         lockedSize = \"{298, 389}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1870&amp;EndingColumnNumber=21&amp;EndingLineNumber=43&amp;StartingColumnNumber=2&amp;StartingLineNumber=43&amp;Timestamp=575824644.161056\"\n         lockedSize = \"{475, 564}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n      <LoggerValueHistoryTimelineItem\n         documentLocation = \"file:///Users/barreto/Development/iOS/opensource/Eureka/Eureka.playground#CharacterRangeLen=19&amp;CharacterRangeLoc=1790&amp;EndingColumnNumber=5&amp;EndingLineNumber=42&amp;StartingColumnNumber=101&amp;StartingLineNumber=41&amp;Timestamp=575824644.161153\"\n         lockedSize = \"{397, 516}\"\n         selectedRepresentationIndex = \"0\"\n         shouldTrackSuperviewWidth = \"NO\">\n      </LoggerValueHistoryTimelineItem>\n   </TimelineItems>\n</Timeline>\n"
  },
  {
    "path": "Eureka.podspec",
    "content": "Pod::Spec.new do |s|\n  s.name = 'Eureka'\n  s.version = '5.5.0'\n  s.license = 'MIT'\n  s.summary = 'Elegant iOS Forms in pure Swift'\n  s.homepage = 'https://github.com/xmartlabs/Eureka'\n  s.social_media_url = 'http://twitter.com/xmartlabs'\n  s.authors = { 'Martin Barreto' => 'martin@xmartlabs.com', 'Mathias Claassen' => 'mathias@xmartlabs.com' }\n  s.source = { :git => 'https://github.com/xmartlabs/Eureka.git', :tag => s.version }\n  s.ios.deployment_target = '9.0'\n  s.ios.frameworks = 'UIKit', 'Foundation'\n  s.source_files = 'Source/**/*.swift'\n  s.requires_arc = true\n  s.swift_version = '5.0'\nend\n"
  },
  {
    "path": "Eureka.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t280FBE5D1D87360900900064 /* RuleRange.swift in Sources */ = {isa = PBXBuildFile; fileRef = 280FBE5C1D87360900900064 /* RuleRange.swift */; };\n\t\t280FBE5F1D873CCE00900064 /* RuleClosure.swift in Sources */ = {isa = PBXBuildFile; fileRef = 280FBE5E1D873CCE00900064 /* RuleClosure.swift */; };\n\t\t2859CD951C7CF1FD0002982F /* Core.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CD921C7CF1FD0002982F /* Core.swift */; };\n\t\t2859CD961C7CF1FD0002982F /* Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CD931C7CF1FD0002982F /* Helpers.swift */; };\n\t\t2859CDBE1C7D137D0002982F /* Form.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDBD1C7D137D0002982F /* Form.swift */; };\n\t\t2859CDC01C7D138D0002982F /* Section.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDBF1C7D138D0002982F /* Section.swift */; };\n\t\t2859CDC41C7D19C50002982F /* HeaderFooterView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDC31C7D19C50002982F /* HeaderFooterView.swift */; };\n\t\t2859CDC61C7D1A2E0002982F /* NavigationAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDC51C7D1A2E0002982F /* NavigationAccessoryView.swift */; };\n\t\t2859CDE91C7DD78E0002982F /* BaseRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDE81C7DD78E0002982F /* BaseRow.swift */; };\n\t\t285BA44A1E8187480034EE92 /* MultivaluedSectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 285BA4481E81864E0034EE92 /* MultivaluedSectionTests.swift */; };\n\t\t287A142B1D89DF1E00FFE6EB /* ValidationsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287A142A1D89DF1E00FFE6EB /* ValidationsTests.swift */; };\n\t\t287A14331D8A07ED00FFE6EB /* SelectableSectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287A142D1D8A07B700FFE6EB /* SelectableSectionTests.swift */; };\n\t\t287E7D7E1D625A260065F4DE /* RuleRequired.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E7D7D1D625A260065F4DE /* RuleRequired.swift */; };\n\t\t287E7D801D74E42D0065F4DE /* RuleRegExp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E7D7F1D74E42D0065F4DE /* RuleRegExp.swift */; };\n\t\t287E7D821D74E64C0065F4DE /* RuleURL.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E7D811D74E64C0065F4DE /* RuleURL.swift */; };\n\t\t287E7D841D75F9C80065F4DE /* RuleEmail.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E7D831D75F9C80065F4DE /* RuleEmail.swift */; };\n\t\t287E7D901D7601850065F4DE /* RuleLength.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287E7D8F1D7601850065F4DE /* RuleLength.swift */; };\n\t\t28B12FD51BA0E83C00F27A23 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 28B12FD41BA0E83C00F27A23 /* Assets.xcassets */; };\n\t\t28B1D7871C7F911900605EB3 /* BaseEurekaTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7711C7F90C900605EB3 /* BaseEurekaTests.swift */; };\n\t\t28B1D7881C7F911900605EB3 /* CallbacksTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7721C7F90C900605EB3 /* CallbacksTests.swift */; };\n\t\t28B1D7891C7F911900605EB3 /* CollectionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7731C7F90C900605EB3 /* CollectionTests.swift */; };\n\t\t28B1D78A1C7F911900605EB3 /* DateTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7741C7F90C900605EB3 /* DateTests.swift */; };\n\t\t28B1D78B1C7F911900605EB3 /* FormValuesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7751C7F90C900605EB3 /* FormValuesTests.swift */; };\n\t\t28B1D78C1C7F911900605EB3 /* HelperMethodTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7761C7F90C900605EB3 /* HelperMethodTests.swift */; };\n\t\t28B1D78D1C7F911900605EB3 /* HiddenRowsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7771C7F90C900605EB3 /* HiddenRowsTests.swift */; };\n\t\t28B1D78E1C7F911900605EB3 /* OperatorsTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7781C7F90C900605EB3 /* OperatorsTest.swift */; };\n\t\t28B1D78F1C7F911900605EB3 /* RowByTagTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D7791C7F90C900605EB3 /* RowByTagTests.swift */; };\n\t\t28B1D7901C7F911900605EB3 /* RowCallbackTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D77A1C7F90C900605EB3 /* RowCallbackTests.swift */; };\n\t\t28B1D7911C7F911900605EB3 /* SetValuesTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28B1D77B1C7F90C900605EB3 /* SetValuesTests.swift */; };\n\t\t28DB37301CE4F864009E46BA /* Protocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28DB372F1CE4F864009E46BA /* Protocols.swift */; };\n\t\t28EE0FDE1D5E889F00B91340 /* Validation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EE0FDD1D5E889F00B91340 /* Validation.swift */; };\n\t\t28EE46A81C7F5D5200EFF4A2 /* SelectableSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE231C7E141B0002982F /* SelectableSection.swift */; };\n\t\t28EE46A91C7F685900EFF4A2 /* PushRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDEC1C7DF0680002982F /* PushRow.swift */; };\n\t\t28EE46AC1C7F712300EFF4A2 /* DateInlineRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDF41C7DF2740002982F /* DateInlineRow.swift */; };\n\t\t28EEBFE81C7E1D7E00300699 /* CellType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFE41C7E1B3B00300699 /* CellType.swift */; };\n\t\t28EEBFEC1C7E224200300699 /* PresenterRowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFEB1C7E224200300699 /* PresenterRowType.swift */; };\n\t\t28EEBFEE1C7E231C00300699 /* RowControllerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFED1C7E231C00300699 /* RowControllerType.swift */; };\n\t\t28EEBFF01C7E23F400300699 /* Row.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFEF1C7E23F400300699 /* Row.swift */; };\n\t\t28EEBFF21C7E23FA00300699 /* RowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFF11C7E23FA00300699 /* RowType.swift */; };\n\t\t28EEBFF41C7E240000300699 /* RowProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFF31C7E240000300699 /* RowProtocols.swift */; };\n\t\t28EEBFF61C7E240B00300699 /* InlineRowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFF51C7E240B00300699 /* InlineRowType.swift */; };\n\t\t28EEBFF81C7E241200300699 /* SelectableRowType.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFF71C7E241200300699 /* SelectableRowType.swift */; };\n\t\t28EEBFFB1C7E25C500300699 /* Operators.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFFA1C7E25C500300699 /* Operators.swift */; };\n\t\t28EEBFFD1C7E25F100300699 /* Cell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28EEBFFC1C7E25F100300699 /* Cell.swift */; };\n\t\t28EEBFFE1C7E281F00300699 /* CheckRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDA41C7CF51A0002982F /* CheckRow.swift */; };\n\t\t28EEC0001C7E36EB00300699 /* SwitchRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDA61C7CF5530002982F /* SwitchRow.swift */; };\n\t\t28EEC0021C7E37BD00300699 /* ButtonRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDA21C7CF4050002982F /* ButtonRow.swift */; };\n\t\t28EEC0031C7E390300300699 /* DecimalFormatter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE0A1C7E003B0002982F /* DecimalFormatter.swift */; };\n\t\t28EEC00B1C7E395700300699 /* OptionsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDB31C7D0E4B0002982F /* OptionsRow.swift */; };\n\t\t28EEC00C1C7E396000300699 /* SelectorRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDBB1C7D12930002982F /* SelectorRow.swift */; };\n\t\t28EEC00E1C7E398A00300699 /* DateFieldRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDEE1C7DF0F70002982F /* DateFieldRow.swift */; };\n\t\t28EEC00F1C7E398D00300699 /* FieldRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDF01C7DF1620002982F /* FieldRow.swift */; };\n\t\t28EEC0101C7E399500300699 /* DateInlineFieldRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDF21C7DF22D0002982F /* DateInlineFieldRow.swift */; };\n\t\t28EEC0121C7E399500300699 /* GenericMultipleSelectorRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE211C7E13470002982F /* GenericMultipleSelectorRow.swift */; };\n\t\t28EEC0151C7E39C100300699 /* DateRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDFE1C7DF9A70002982F /* DateRow.swift */; };\n\t\t28EEC0161C7E3A3200300699 /* ListCheckRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE1B1C7E04630002982F /* ListCheckRow.swift */; };\n\t\t28EEC0181C7E3A3D00300699 /* MultipleSelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE121C7E02310002982F /* MultipleSelectorViewController.swift */; };\n\t\t28EEC0191C7E3A3D00300699 /* SelectorAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE141C7E02710002982F /* SelectorAlertController.swift */; };\n\t\t28EEC01C1C7E3A7400300699 /* ButtonRowWithPresent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CD991C7CF2020002982F /* ButtonRowWithPresent.swift */; };\n\t\t28EEC01D1C7E3A8600300699 /* SliderRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CD9A1C7CF2020002982F /* SliderRow.swift */; };\n\t\t28EEC01F1C7E3AC800300699 /* LabelRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDA01C7CF3A10002982F /* LabelRow.swift */; };\n\t\t28EEC0201C7E3AD200300699 /* SegmentedRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDA81C7D0B3C0002982F /* SegmentedRow.swift */; };\n\t\t28EEC0211C7E3AD700300699 /* TextAreaRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDAC1C7D0BCA0002982F /* TextAreaRow.swift */; };\n\t\t28EEC0221C7E3B1300300699 /* ActionSheetRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDAE1C7D0D990002982F /* ActionSheetRow.swift */; };\n\t\t28EEC0231C7E3B1900300699 /* AlertRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDB01C7D0E010002982F /* AlertRow.swift */; };\n\t\t28EEC0241C7E3B1D00300699 /* PickerRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDB51C7D0EC60002982F /* PickerRow.swift */; };\n\t\t28EEC0251C7E3B2200300699 /* PickerInlineRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDB71C7D0FE70002982F /* PickerInlineRow.swift */; };\n\t\t28EEC0281C7E3B4B00300699 /* FieldsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE061C7DFBFA0002982F /* FieldsRow.swift */; };\n\t\t28EEC02A1C7E3B5A00300699 /* MultipleSelectorRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE1F1C7E092B0002982F /* MultipleSelectorRow.swift */; };\n\t\t28EEC02F1C7E49BF00300699 /* SelectorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE101C7E01EE0002982F /* SelectorViewController.swift */; };\n\t\t28EEC0321C7E64A400300699 /* DatePickerRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CDFC1C7DF9430002982F /* DatePickerRow.swift */; };\n\t\t28EEC0331C7E64AB00300699 /* PopoverSelectorRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2859CE1D1C7E08300002982F /* PopoverSelectorRow.swift */; };\n\t\t3973000A1DF0E2A000080E4D /* PickerInputRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 397300091DF0E2A000080E4D /* PickerInputRow.swift */; };\n\t\t49ADC7F91C8A83240073952B /* StepperRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 49ADC7F81C8A83240073952B /* StepperRow.swift */; };\n\t\t51729DF61B9A4F5E004A00EB /* Eureka.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51729DEB1B9A4F5E004A00EB /* Eureka.framework */; };\n\t\t51729E671B9A5FA5004A00EB /* Eureka.h in Headers */ = {isa = PBXBuildFile; fileRef = 51729E661B9A5FA5004A00EB /* Eureka.h */; settings = {ATTRIBUTES = (Public, ); }; };\n\t\t798C5ADA1EF1E35600A21F52 /* SwipeActions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 798C5AD91EF1E35600A21F52 /* SwipeActions.swift */; };\n\t\t8FCCF8EF20A24085004793A0 /* DoublePickerRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCCF8EE20A24085004793A0 /* DoublePickerRow.swift */; };\n\t\t8FCCF8F120A32613004793A0 /* TriplePickerRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCCF8F020A32613004793A0 /* TriplePickerRow.swift */; };\n\t\t8FCCF92320A473E7004793A0 /* DoublePickerInputRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCCF92220A473E7004793A0 /* DoublePickerInputRow.swift */; };\n\t\t8FCCF92520A4794B004793A0 /* TriplePickerInputRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8FCCF92420A4794B004793A0 /* TriplePickerInputRow.swift */; };\n\t\t9EFC727C291D0369004840A9 /* ResultBuildersTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EFC727B291D0369004840A9 /* ResultBuildersTests.swift */; };\n\t\t9EFC727F291D05FB004840A9 /* ResultBuilders.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9EFC727D291D05EA004840A9 /* ResultBuilders.swift */; };\n\t\tB244E6541FE1C94F0026B944 /* AlertOptionsRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = B244E6531FE1C94F0026B944 /* AlertOptionsRow.swift */; };\n\t\tB257FE2E1EC0F66900043911 /* RowsInsertionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B257FE2D1EC0F66900043911 /* RowsInsertionTests.swift */; };\n\t\tB2A401161EC0BA140042EDF0 /* SectionsInsertionTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2A401151EC0BA140042EDF0 /* SectionsInsertionTests.swift */; };\n\t\tE110A1402BC9D08200FFD81D /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = E110A13F2BC9D08200FFD81D /* PrivacyInfo.xcprivacy */; };\n\t\tFA56B6AF1DBAD38900407C94 /* RuleEqualsToRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = FA56B6AE1DBAD38900407C94 /* RuleEqualsToRow.swift */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t51729DF71B9A4F5E004A00EB /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729DE21B9A4F5E004A00EB /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 51729DEA1B9A4F5E004A00EB;\n\t\t\tremoteInfo = Eureka;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXFileReference section */\n\t\t280FBE5C1D87360900900064 /* RuleRange.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleRange.swift; path = Source/Validations/RuleRange.swift; sourceTree = SOURCE_ROOT; };\n\t\t280FBE5E1D873CCE00900064 /* RuleClosure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleClosure.swift; path = Source/Validations/RuleClosure.swift; sourceTree = SOURCE_ROOT; };\n\t\t2859CD921C7CF1FD0002982F /* Core.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Core.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CD931C7CF1FD0002982F /* Helpers.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Helpers.swift; sourceTree = \"<group>\"; };\n\t\t2859CD991C7CF2020002982F /* ButtonRowWithPresent.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ButtonRowWithPresent.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CD9A1C7CF2020002982F /* SliderRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SliderRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDA01C7CF3A10002982F /* LabelRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LabelRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDA21C7CF4050002982F /* ButtonRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ButtonRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDA41C7CF51A0002982F /* CheckRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CheckRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDA61C7CF5530002982F /* SwitchRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SwitchRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDA81C7D0B3C0002982F /* SegmentedRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SegmentedRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDAC1C7D0BCA0002982F /* TextAreaRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TextAreaRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDAE1C7D0D990002982F /* ActionSheetRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = ActionSheetRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDB01C7D0E010002982F /* AlertRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = AlertRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDB31C7D0E4B0002982F /* OptionsRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OptionsRow.swift; path = Common/OptionsRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDB51C7D0EC60002982F /* PickerRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDB71C7D0FE70002982F /* PickerInlineRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerInlineRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDBB1C7D12930002982F /* SelectorRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectorRow.swift; path = Common/SelectorRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDBD1C7D137D0002982F /* Form.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Form.swift; sourceTree = \"<group>\"; };\n\t\t2859CDBF1C7D138D0002982F /* Section.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Section.swift; sourceTree = \"<group>\"; };\n\t\t2859CDC31C7D19C50002982F /* HeaderFooterView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = HeaderFooterView.swift; sourceTree = \"<group>\"; };\n\t\t2859CDC51C7D1A2E0002982F /* NavigationAccessoryView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = NavigationAccessoryView.swift; sourceTree = \"<group>\"; };\n\t\t2859CDE81C7DD78E0002982F /* BaseRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = BaseRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDEC1C7DF0680002982F /* PushRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PushRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDEE1C7DF0F70002982F /* DateFieldRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = DateFieldRow.swift; path = Common/DateFieldRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDF01C7DF1620002982F /* FieldRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FieldRow.swift; path = Common/FieldRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDF21C7DF22D0002982F /* DateInlineFieldRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = DateInlineFieldRow.swift; path = Common/DateInlineFieldRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDF41C7DF2740002982F /* DateInlineRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = DateInlineRow.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t2859CDFC1C7DF9430002982F /* DatePickerRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DatePickerRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CDFE1C7DF9A70002982F /* DateRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DateRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE061C7DFBFA0002982F /* FieldsRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = FieldsRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE0A1C7E003B0002982F /* DecimalFormatter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DecimalFormatter.swift; path = Common/DecimalFormatter.swift; sourceTree = \"<group>\"; };\n\t\t2859CE101C7E01EE0002982F /* SelectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectorViewController.swift; path = Controllers/SelectorViewController.swift; sourceTree = \"<group>\"; };\n\t\t2859CE121C7E02310002982F /* MultipleSelectorViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MultipleSelectorViewController.swift; path = Controllers/MultipleSelectorViewController.swift; sourceTree = \"<group>\"; };\n\t\t2859CE141C7E02710002982F /* SelectorAlertController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectorAlertController.swift; path = Controllers/SelectorAlertController.swift; sourceTree = \"<group>\"; };\n\t\t2859CE1B1C7E04630002982F /* ListCheckRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ListCheckRow.swift; path = SelectableRows/ListCheckRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE1D1C7E08300002982F /* PopoverSelectorRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PopoverSelectorRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE1F1C7E092B0002982F /* MultipleSelectorRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MultipleSelectorRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE211C7E13470002982F /* GenericMultipleSelectorRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = GenericMultipleSelectorRow.swift; path = Common/GenericMultipleSelectorRow.swift; sourceTree = \"<group>\"; };\n\t\t2859CE231C7E141B0002982F /* SelectableSection.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectableSection.swift; sourceTree = \"<group>\"; };\n\t\t285BA4481E81864E0034EE92 /* MultivaluedSectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = MultivaluedSectionTests.swift; path = Tests/MultivaluedSectionTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t287A142A1D89DF1E00FFE6EB /* ValidationsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ValidationsTests.swift; path = Tests/ValidationsTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t287A142D1D8A07B700FFE6EB /* SelectableSectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SelectableSectionTests.swift; path = Tests/SelectableSectionTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t287E7D7D1D625A260065F4DE /* RuleRequired.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleRequired.swift; path = Source/Validations/RuleRequired.swift; sourceTree = SOURCE_ROOT; };\n\t\t287E7D7F1D74E42D0065F4DE /* RuleRegExp.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleRegExp.swift; path = Source/Validations/RuleRegExp.swift; sourceTree = SOURCE_ROOT; };\n\t\t287E7D811D74E64C0065F4DE /* RuleURL.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleURL.swift; path = Source/Validations/RuleURL.swift; sourceTree = SOURCE_ROOT; };\n\t\t287E7D831D75F9C80065F4DE /* RuleEmail.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleEmail.swift; path = Source/Validations/RuleEmail.swift; sourceTree = SOURCE_ROOT; };\n\t\t287E7D8F1D7601850065F4DE /* RuleLength.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleLength.swift; path = Source/Validations/RuleLength.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B12FD41BA0E83C00F27A23 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Source/Assets.xcassets; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7711C7F90C900605EB3 /* BaseEurekaTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = BaseEurekaTests.swift; path = Tests/BaseEurekaTests.swift; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t28B1D7721C7F90C900605EB3 /* CallbacksTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = CallbacksTests.swift; path = Tests/CallbacksTests.swift; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t28B1D7731C7F90C900605EB3 /* CollectionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CollectionTests.swift; path = Tests/CollectionTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7741C7F90C900605EB3 /* DateTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = DateTests.swift; path = Tests/DateTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7751C7F90C900605EB3 /* FormValuesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FormValuesTests.swift; path = Tests/FormValuesTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7761C7F90C900605EB3 /* HelperMethodTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HelperMethodTests.swift; path = Tests/HelperMethodTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7771C7F90C900605EB3 /* HiddenRowsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = HiddenRowsTests.swift; path = Tests/HiddenRowsTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7781C7F90C900605EB3 /* OperatorsTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OperatorsTest.swift; path = Tests/OperatorsTest.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D7791C7F90C900605EB3 /* RowByTagTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RowByTagTests.swift; path = Tests/RowByTagTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D77A1C7F90C900605EB3 /* RowCallbackTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RowCallbackTests.swift; path = Tests/RowCallbackTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28B1D77B1C7F90C900605EB3 /* SetValuesTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SetValuesTests.swift; path = Tests/SetValuesTests.swift; sourceTree = SOURCE_ROOT; };\n\t\t28DB372F1CE4F864009E46BA /* Protocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Protocols.swift; path = Common/Protocols.swift; sourceTree = \"<group>\"; };\n\t\t28EE0FDD1D5E889F00B91340 /* Validation.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Validation.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFE41C7E1B3B00300699 /* CellType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = CellType.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t28EEBFEB1C7E224200300699 /* PresenterRowType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PresenterRowType.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFED1C7E231C00300699 /* RowControllerType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowControllerType.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFEF1C7E23F400300699 /* Row.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Row.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFF11C7E23FA00300699 /* RowType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowType.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFF31C7E240000300699 /* RowProtocols.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = RowProtocols.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFF51C7E240B00300699 /* InlineRowType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InlineRowType.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFF71C7E241200300699 /* SelectableRowType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SelectableRowType.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFFA1C7E25C500300699 /* Operators.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Operators.swift; sourceTree = \"<group>\"; };\n\t\t28EEBFFC1C7E25F100300699 /* Cell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = Cell.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t397300091DF0E2A000080E4D /* PickerInputRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PickerInputRow.swift; sourceTree = \"<group>\"; };\n\t\t49ADC7F81C8A83240073952B /* StepperRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StepperRow.swift; sourceTree = \"<group>\"; };\n\t\t51729DEB1B9A4F5E004A00EB /* Eureka.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Eureka.framework; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t51729DF01B9A4F5E004A00EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n\t\t51729DF51B9A4F5E004A00EB /* EurekaTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = EurekaTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t51729DFC1B9A4F5E004A00EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = ../Tests/Info.plist; sourceTree = \"<group>\"; };\n\t\t51729E661B9A5FA5004A00EB /* Eureka.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Eureka.h; path = Source/Eureka.h; sourceTree = SOURCE_ROOT; };\n\t\t798C5AD91EF1E35600A21F52 /* SwipeActions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeActions.swift; sourceTree = \"<group>\"; };\n\t\t8FCCF8EE20A24085004793A0 /* DoublePickerRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoublePickerRow.swift; sourceTree = \"<group>\"; };\n\t\t8FCCF8F020A32613004793A0 /* TriplePickerRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriplePickerRow.swift; sourceTree = \"<group>\"; };\n\t\t8FCCF92220A473E7004793A0 /* DoublePickerInputRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DoublePickerInputRow.swift; sourceTree = \"<group>\"; };\n\t\t8FCCF92420A4794B004793A0 /* TriplePickerInputRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TriplePickerInputRow.swift; sourceTree = \"<group>\"; };\n\t\t9EFC727B291D0369004840A9 /* ResultBuildersTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultBuildersTests.swift; sourceTree = \"<group>\"; };\n\t\t9EFC727D291D05EA004840A9 /* ResultBuilders.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ResultBuilders.swift; sourceTree = \"<group>\"; };\n\t\tB244E6531FE1C94F0026B944 /* AlertOptionsRow.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AlertOptionsRow.swift; path = Common/AlertOptionsRow.swift; sourceTree = \"<group>\"; };\n\t\tB257FE2D1EC0F66900043911 /* RowsInsertionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RowsInsertionTests.swift; path = Tests/RowsInsertionTests.swift; sourceTree = SOURCE_ROOT; };\n\t\tB2A401151EC0BA140042EDF0 /* SectionsInsertionTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SectionsInsertionTests.swift; path = Tests/SectionsInsertionTests.swift; sourceTree = SOURCE_ROOT; };\n\t\tE110A13F2BC9D08200FFD81D /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = \"<group>\"; };\n\t\tFA56B6AE1DBAD38900407C94 /* RuleEqualsToRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = RuleEqualsToRow.swift; path = Source/Validations/RuleEqualsToRow.swift; sourceTree = SOURCE_ROOT; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t51729DE71B9A4F5E004A00EB /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729DF21B9A4F5E004A00EB /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t51729DF61B9A4F5E004A00EB /* Eureka.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t2859CD901C7CF1FD0002982F /* Core */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CDE81C7DD78E0002982F /* BaseRow.swift */,\n\t\t\t\t28EEBFFC1C7E25F100300699 /* Cell.swift */,\n\t\t\t\t28EEBFE41C7E1B3B00300699 /* CellType.swift */,\n\t\t\t\t2859CD921C7CF1FD0002982F /* Core.swift */,\n\t\t\t\t2859CDBD1C7D137D0002982F /* Form.swift */,\n\t\t\t\t2859CDC31C7D19C50002982F /* HeaderFooterView.swift */,\n\t\t\t\t2859CD931C7CF1FD0002982F /* Helpers.swift */,\n\t\t\t\t28EEBFF51C7E240B00300699 /* InlineRowType.swift */,\n\t\t\t\t2859CDC51C7D1A2E0002982F /* NavigationAccessoryView.swift */,\n\t\t\t\t28EEBFFA1C7E25C500300699 /* Operators.swift */,\n\t\t\t\t28EEBFEB1C7E224200300699 /* PresenterRowType.swift */,\n\t\t\t\t9EFC727D291D05EA004840A9 /* ResultBuilders.swift */,\n\t\t\t\t28EEBFEF1C7E23F400300699 /* Row.swift */,\n\t\t\t\t28EEBFED1C7E231C00300699 /* RowControllerType.swift */,\n\t\t\t\t28EEBFF31C7E240000300699 /* RowProtocols.swift */,\n\t\t\t\t28EEBFF11C7E23FA00300699 /* RowType.swift */,\n\t\t\t\t28EEBFF71C7E241200300699 /* SelectableRowType.swift */,\n\t\t\t\t2859CDBF1C7D138D0002982F /* Section.swift */,\n\t\t\t\t2859CE231C7E141B0002982F /* SelectableSection.swift */,\n\t\t\t\t798C5AD91EF1E35600A21F52 /* SwipeActions.swift */,\n\t\t\t\t28EE0FDD1D5E889F00B91340 /* Validation.swift */,\n\t\t\t);\n\t\t\tname = Core;\n\t\t\tpath = Source/Core;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t2859CD971C7CF2020002982F /* Rows */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CE1A1C7E04250002982F /* SelectableRows */,\n\t\t\t\t2859CE0F1C7E01C70002982F /* Controllers */,\n\t\t\t\t2859CDB21C7D0E210002982F /* Common */,\n\t\t\t\t2859CDAE1C7D0D990002982F /* ActionSheetRow.swift */,\n\t\t\t\t2859CDB01C7D0E010002982F /* AlertRow.swift */,\n\t\t\t\t2859CDA21C7CF4050002982F /* ButtonRow.swift */,\n\t\t\t\t2859CD991C7CF2020002982F /* ButtonRowWithPresent.swift */,\n\t\t\t\t2859CDA41C7CF51A0002982F /* CheckRow.swift */,\n\t\t\t\t2859CDFE1C7DF9A70002982F /* DateRow.swift */,\n\t\t\t\t2859CDF41C7DF2740002982F /* DateInlineRow.swift */,\n\t\t\t\t2859CDFC1C7DF9430002982F /* DatePickerRow.swift */,\n\t\t\t\t8FCCF92220A473E7004793A0 /* DoublePickerInputRow.swift */,\n\t\t\t\t8FCCF8EE20A24085004793A0 /* DoublePickerRow.swift */,\n\t\t\t\t2859CE061C7DFBFA0002982F /* FieldsRow.swift */,\n\t\t\t\t2859CDA01C7CF3A10002982F /* LabelRow.swift */,\n\t\t\t\t2859CE1F1C7E092B0002982F /* MultipleSelectorRow.swift */,\n\t\t\t\t2859CDB51C7D0EC60002982F /* PickerRow.swift */,\n\t\t\t\t397300091DF0E2A000080E4D /* PickerInputRow.swift */,\n\t\t\t\t2859CDB71C7D0FE70002982F /* PickerInlineRow.swift */,\n\t\t\t\t2859CE1D1C7E08300002982F /* PopoverSelectorRow.swift */,\n\t\t\t\t2859CDEC1C7DF0680002982F /* PushRow.swift */,\n\t\t\t\t2859CDA81C7D0B3C0002982F /* SegmentedRow.swift */,\n\t\t\t\t2859CD9A1C7CF2020002982F /* SliderRow.swift */,\n\t\t\t\t49ADC7F81C8A83240073952B /* StepperRow.swift */,\n\t\t\t\t2859CDA61C7CF5530002982F /* SwitchRow.swift */,\n\t\t\t\t2859CDAC1C7D0BCA0002982F /* TextAreaRow.swift */,\n\t\t\t\t8FCCF92420A4794B004793A0 /* TriplePickerInputRow.swift */,\n\t\t\t\t8FCCF8F020A32613004793A0 /* TriplePickerRow.swift */,\n\t\t\t);\n\t\t\tname = Rows;\n\t\t\tpath = Source/Rows;\n\t\t\tsourceTree = SOURCE_ROOT;\n\t\t};\n\t\t2859CDB21C7D0E210002982F /* Common */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CDF01C7DF1620002982F /* FieldRow.swift */,\n\t\t\t\t2859CDB31C7D0E4B0002982F /* OptionsRow.swift */,\n\t\t\t\tB244E6531FE1C94F0026B944 /* AlertOptionsRow.swift */,\n\t\t\t\t2859CDBB1C7D12930002982F /* SelectorRow.swift */,\n\t\t\t\t2859CDEE1C7DF0F70002982F /* DateFieldRow.swift */,\n\t\t\t\t2859CDF21C7DF22D0002982F /* DateInlineFieldRow.swift */,\n\t\t\t\t2859CE0A1C7E003B0002982F /* DecimalFormatter.swift */,\n\t\t\t\t2859CE211C7E13470002982F /* GenericMultipleSelectorRow.swift */,\n\t\t\t\t28DB372F1CE4F864009E46BA /* Protocols.swift */,\n\t\t\t);\n\t\t\tname = Common;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t2859CE0F1C7E01C70002982F /* Controllers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CE101C7E01EE0002982F /* SelectorViewController.swift */,\n\t\t\t\t2859CE141C7E02710002982F /* SelectorAlertController.swift */,\n\t\t\t\t2859CE121C7E02310002982F /* MultipleSelectorViewController.swift */,\n\t\t\t);\n\t\t\tname = Controllers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t2859CE1A1C7E04250002982F /* SelectableRows */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CE1B1C7E04630002982F /* ListCheckRow.swift */,\n\t\t\t);\n\t\t\tname = SelectableRows;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t287E7D7C1D62552C0065F4DE /* Validations */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t287E7D7D1D625A260065F4DE /* RuleRequired.swift */,\n\t\t\t\t287E7D7F1D74E42D0065F4DE /* RuleRegExp.swift */,\n\t\t\t\t287E7D831D75F9C80065F4DE /* RuleEmail.swift */,\n\t\t\t\t287E7D811D74E64C0065F4DE /* RuleURL.swift */,\n\t\t\t\t280FBE5C1D87360900900064 /* RuleRange.swift */,\n\t\t\t\t287E7D8F1D7601850065F4DE /* RuleLength.swift */,\n\t\t\t\t280FBE5E1D873CCE00900064 /* RuleClosure.swift */,\n\t\t\t\tFA56B6AE1DBAD38900407C94 /* RuleEqualsToRow.swift */,\n\t\t\t);\n\t\t\tpath = Validations;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729DE11B9A4F5E004A00EB = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t51729DED1B9A4F5E004A00EB /* Source */,\n\t\t\t\t51729DF91B9A4F5E004A00EB /* Tests */,\n\t\t\t\t51729DEC1B9A4F5E004A00EB /* Products */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729DEC1B9A4F5E004A00EB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t51729DEB1B9A4F5E004A00EB /* Eureka.framework */,\n\t\t\t\t51729DF51B9A4F5E004A00EB /* EurekaTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729DED1B9A4F5E004A00EB /* Source */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2859CD901C7CF1FD0002982F /* Core */,\n\t\t\t\t2859CD971C7CF2020002982F /* Rows */,\n\t\t\t\t287E7D7C1D62552C0065F4DE /* Validations */,\n\t\t\t\t51729E661B9A5FA5004A00EB /* Eureka.h */,\n\t\t\t\tE110A13F2BC9D08200FFD81D /* PrivacyInfo.xcprivacy */,\n\t\t\t\t51729DF01B9A4F5E004A00EB /* Info.plist */,\n\t\t\t\t28B12FD41BA0E83C00F27A23 /* Assets.xcassets */,\n\t\t\t);\n\t\t\tpath = Source;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729DF91B9A4F5E004A00EB /* Tests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t287A142D1D8A07B700FFE6EB /* SelectableSectionTests.swift */,\n\t\t\t\t28B1D7711C7F90C900605EB3 /* BaseEurekaTests.swift */,\n\t\t\t\t28B1D7721C7F90C900605EB3 /* CallbacksTests.swift */,\n\t\t\t\t28B1D7731C7F90C900605EB3 /* CollectionTests.swift */,\n\t\t\t\t28B1D7741C7F90C900605EB3 /* DateTests.swift */,\n\t\t\t\t28B1D7751C7F90C900605EB3 /* FormValuesTests.swift */,\n\t\t\t\t28B1D7761C7F90C900605EB3 /* HelperMethodTests.swift */,\n\t\t\t\t28B1D7771C7F90C900605EB3 /* HiddenRowsTests.swift */,\n\t\t\t\t28B1D7781C7F90C900605EB3 /* OperatorsTest.swift */,\n\t\t\t\t9EFC727B291D0369004840A9 /* ResultBuildersTests.swift */,\n\t\t\t\t28B1D7791C7F90C900605EB3 /* RowByTagTests.swift */,\n\t\t\t\t28B1D77A1C7F90C900605EB3 /* RowCallbackTests.swift */,\n\t\t\t\t28B1D77B1C7F90C900605EB3 /* SetValuesTests.swift */,\n\t\t\t\t287A142A1D89DF1E00FFE6EB /* ValidationsTests.swift */,\n\t\t\t\t285BA4481E81864E0034EE92 /* MultivaluedSectionTests.swift */,\n\t\t\t\t51729DFC1B9A4F5E004A00EB /* Info.plist */,\n\t\t\t\tB2A401151EC0BA140042EDF0 /* SectionsInsertionTests.swift */,\n\t\t\t\tB257FE2D1EC0F66900043911 /* RowsInsertionTests.swift */,\n\t\t\t);\n\t\t\tpath = Tests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXHeadersBuildPhase section */\n\t\t51729DE81B9A4F5E004A00EB /* Headers */ = {\n\t\t\tisa = PBXHeadersBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t51729E671B9A5FA5004A00EB /* Eureka.h in Headers */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXHeadersBuildPhase section */\n\n/* Begin PBXNativeTarget section */\n\t\t51729DEA1B9A4F5E004A00EB /* Eureka */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 51729DFF1B9A4F5E004A00EB /* Build configuration list for PBXNativeTarget \"Eureka\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t51729DE61B9A4F5E004A00EB /* Sources */,\n\t\t\t\t51729DE71B9A4F5E004A00EB /* Frameworks */,\n\t\t\t\t51729DE81B9A4F5E004A00EB /* Headers */,\n\t\t\t\t51729DE91B9A4F5E004A00EB /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Eureka;\n\t\t\tproductName = Eureka;\n\t\t\tproductReference = 51729DEB1B9A4F5E004A00EB /* Eureka.framework */;\n\t\t\tproductType = \"com.apple.product-type.framework\";\n\t\t};\n\t\t51729DF41B9A4F5E004A00EB /* EurekaTests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 51729E021B9A4F5E004A00EB /* Build configuration list for PBXNativeTarget \"EurekaTests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t51729DF11B9A4F5E004A00EB /* Sources */,\n\t\t\t\t51729DF21B9A4F5E004A00EB /* Frameworks */,\n\t\t\t\t51729DF31B9A4F5E004A00EB /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t51729DF81B9A4F5E004A00EB /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = EurekaTests;\n\t\t\tproductName = EurekaTests;\n\t\t\tproductReference = 51729DF51B9A4F5E004A00EB /* EurekaTests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.unit-test\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t51729DE21B9A4F5E004A00EB /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastSwiftUpdateCheck = 0700;\n\t\t\t\tLastUpgradeCheck = 1400;\n\t\t\t\tORGANIZATIONNAME = Xmartlabs;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t51729DEA1B9A4F5E004A00EB = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t51729DF41B9A4F5E004A00EB = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 51729DE51B9A4F5E004A00EB /* Build configuration list for PBXProject \"Eureka\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 51729DE11B9A4F5E004A00EB;\n\t\t\tproductRefGroup = 51729DEC1B9A4F5E004A00EB /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t51729DEA1B9A4F5E004A00EB /* Eureka */,\n\t\t\t\t51729DF41B9A4F5E004A00EB /* EurekaTests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t51729DE91B9A4F5E004A00EB /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\tE110A1402BC9D08200FFD81D /* PrivacyInfo.xcprivacy in Resources */,\n\t\t\t\t28B12FD51BA0E83C00F27A23 /* Assets.xcassets in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729DF31B9A4F5E004A00EB /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t51729DE61B9A4F5E004A00EB /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t28EEC0251C7E3B2200300699 /* PickerInlineRow.swift in Sources */,\n\t\t\t\t28EEC0331C7E64AB00300699 /* PopoverSelectorRow.swift in Sources */,\n\t\t\t\t28EEBFF81C7E241200300699 /* SelectableRowType.swift in Sources */,\n\t\t\t\t28EEC0201C7E3AD200300699 /* SegmentedRow.swift in Sources */,\n\t\t\t\t28EEC01F1C7E3AC800300699 /* LabelRow.swift in Sources */,\n\t\t\t\t287E7D7E1D625A260065F4DE /* RuleRequired.swift in Sources */,\n\t\t\t\t28EEC0191C7E3A3D00300699 /* SelectorAlertController.swift in Sources */,\n\t\t\t\t28EEBFEE1C7E231C00300699 /* RowControllerType.swift in Sources */,\n\t\t\t\t28EE46A91C7F685900EFF4A2 /* PushRow.swift in Sources */,\n\t\t\t\t28EEC00F1C7E398D00300699 /* FieldRow.swift in Sources */,\n\t\t\t\t28EEC02F1C7E49BF00300699 /* SelectorViewController.swift in Sources */,\n\t\t\t\t28EEC0031C7E390300300699 /* DecimalFormatter.swift in Sources */,\n\t\t\t\t28EE0FDE1D5E889F00B91340 /* Validation.swift in Sources */,\n\t\t\t\t2859CD951C7CF1FD0002982F /* Core.swift in Sources */,\n\t\t\t\t2859CDBE1C7D137D0002982F /* Form.swift in Sources */,\n\t\t\t\t280FBE5F1D873CCE00900064 /* RuleClosure.swift in Sources */,\n\t\t\t\t28EEC0001C7E36EB00300699 /* SwitchRow.swift in Sources */,\n\t\t\t\t3973000A1DF0E2A000080E4D /* PickerInputRow.swift in Sources */,\n\t\t\t\t287E7D901D7601850065F4DE /* RuleLength.swift in Sources */,\n\t\t\t\t8FCCF8EF20A24085004793A0 /* DoublePickerRow.swift in Sources */,\n\t\t\t\t28EEC02A1C7E3B5A00300699 /* MultipleSelectorRow.swift in Sources */,\n\t\t\t\t28EEC0231C7E3B1900300699 /* AlertRow.swift in Sources */,\n\t\t\t\t28EEC0221C7E3B1300300699 /* ActionSheetRow.swift in Sources */,\n\t\t\t\t28EEBFEC1C7E224200300699 /* PresenterRowType.swift in Sources */,\n\t\t\t\t28EEC0211C7E3AD700300699 /* TextAreaRow.swift in Sources */,\n\t\t\t\t28EEBFFD1C7E25F100300699 /* Cell.swift in Sources */,\n\t\t\t\t28EEC0321C7E64A400300699 /* DatePickerRow.swift in Sources */,\n\t\t\t\tFA56B6AF1DBAD38900407C94 /* RuleEqualsToRow.swift in Sources */,\n\t\t\t\t28EEBFE81C7E1D7E00300699 /* CellType.swift in Sources */,\n\t\t\t\t8FCCF92320A473E7004793A0 /* DoublePickerInputRow.swift in Sources */,\n\t\t\t\t28EEC0241C7E3B1D00300699 /* PickerRow.swift in Sources */,\n\t\t\t\t28EEC0281C7E3B4B00300699 /* FieldsRow.swift in Sources */,\n\t\t\t\t2859CD961C7CF1FD0002982F /* Helpers.swift in Sources */,\n\t\t\t\t287E7D821D74E64C0065F4DE /* RuleURL.swift in Sources */,\n\t\t\t\t28EEBFF21C7E23FA00300699 /* RowType.swift in Sources */,\n\t\t\t\t9EFC727F291D05FB004840A9 /* ResultBuilders.swift in Sources */,\n\t\t\t\t287E7D801D74E42D0065F4DE /* RuleRegExp.swift in Sources */,\n\t\t\t\t28EEC0101C7E399500300699 /* DateInlineFieldRow.swift in Sources */,\n\t\t\t\t2859CDC61C7D1A2E0002982F /* NavigationAccessoryView.swift in Sources */,\n\t\t\t\t49ADC7F91C8A83240073952B /* StepperRow.swift in Sources */,\n\t\t\t\tB244E6541FE1C94F0026B944 /* AlertOptionsRow.swift in Sources */,\n\t\t\t\t28EE46AC1C7F712300EFF4A2 /* DateInlineRow.swift in Sources */,\n\t\t\t\t28EEC01C1C7E3A7400300699 /* ButtonRowWithPresent.swift in Sources */,\n\t\t\t\t798C5ADA1EF1E35600A21F52 /* SwipeActions.swift in Sources */,\n\t\t\t\t28EEBFF41C7E240000300699 /* RowProtocols.swift in Sources */,\n\t\t\t\t28EEBFFE1C7E281F00300699 /* CheckRow.swift in Sources */,\n\t\t\t\t2859CDC41C7D19C50002982F /* HeaderFooterView.swift in Sources */,\n\t\t\t\t28EEC00C1C7E396000300699 /* SelectorRow.swift in Sources */,\n\t\t\t\t280FBE5D1D87360900900064 /* RuleRange.swift in Sources */,\n\t\t\t\t28EEC0161C7E3A3200300699 /* ListCheckRow.swift in Sources */,\n\t\t\t\t28EEC01D1C7E3A8600300699 /* SliderRow.swift in Sources */,\n\t\t\t\t28EEC00B1C7E395700300699 /* OptionsRow.swift in Sources */,\n\t\t\t\t28EEC0021C7E37BD00300699 /* ButtonRow.swift in Sources */,\n\t\t\t\t28EE46A81C7F5D5200EFF4A2 /* SelectableSection.swift in Sources */,\n\t\t\t\t28EEBFF61C7E240B00300699 /* InlineRowType.swift in Sources */,\n\t\t\t\t287E7D841D75F9C80065F4DE /* RuleEmail.swift in Sources */,\n\t\t\t\t8FCCF8F120A32613004793A0 /* TriplePickerRow.swift in Sources */,\n\t\t\t\t28EEBFFB1C7E25C500300699 /* Operators.swift in Sources */,\n\t\t\t\t28DB37301CE4F864009E46BA /* Protocols.swift in Sources */,\n\t\t\t\t2859CDC01C7D138D0002982F /* Section.swift in Sources */,\n\t\t\t\t28EEC0151C7E39C100300699 /* DateRow.swift in Sources */,\n\t\t\t\t2859CDE91C7DD78E0002982F /* BaseRow.swift in Sources */,\n\t\t\t\t8FCCF92520A4794B004793A0 /* TriplePickerInputRow.swift in Sources */,\n\t\t\t\t28EEBFF01C7E23F400300699 /* Row.swift in Sources */,\n\t\t\t\t28EEC0121C7E399500300699 /* GenericMultipleSelectorRow.swift in Sources */,\n\t\t\t\t28EEC0181C7E3A3D00300699 /* MultipleSelectorViewController.swift in Sources */,\n\t\t\t\t28EEC00E1C7E398A00300699 /* DateFieldRow.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729DF11B9A4F5E004A00EB /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t28B1D7881C7F911900605EB3 /* CallbacksTests.swift in Sources */,\n\t\t\t\t28B1D7891C7F911900605EB3 /* CollectionTests.swift in Sources */,\n\t\t\t\t28B1D78C1C7F911900605EB3 /* HelperMethodTests.swift in Sources */,\n\t\t\t\t28B1D78B1C7F911900605EB3 /* FormValuesTests.swift in Sources */,\n\t\t\t\tB2A401161EC0BA140042EDF0 /* SectionsInsertionTests.swift in Sources */,\n\t\t\t\t9EFC727C291D0369004840A9 /* ResultBuildersTests.swift in Sources */,\n\t\t\t\t28B1D7871C7F911900605EB3 /* BaseEurekaTests.swift in Sources */,\n\t\t\t\t28B1D7911C7F911900605EB3 /* SetValuesTests.swift in Sources */,\n\t\t\t\t285BA44A1E8187480034EE92 /* MultivaluedSectionTests.swift in Sources */,\n\t\t\t\t28B1D7901C7F911900605EB3 /* RowCallbackTests.swift in Sources */,\n\t\t\t\t28B1D78E1C7F911900605EB3 /* OperatorsTest.swift in Sources */,\n\t\t\t\t28B1D78D1C7F911900605EB3 /* HiddenRowsTests.swift in Sources */,\n\t\t\t\t287A14331D8A07ED00FFE6EB /* SelectableSectionTests.swift in Sources */,\n\t\t\t\tB257FE2E1EC0F66900043911 /* RowsInsertionTests.swift in Sources */,\n\t\t\t\t28B1D78A1C7F911900605EB3 /* DateTests.swift in Sources */,\n\t\t\t\t287A142B1D89DF1E00FFE6EB /* ValidationsTests.swift in Sources */,\n\t\t\t\t28B1D78F1C7F911900605EB3 /* RowByTagTests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t51729DF81B9A4F5E004A00EB /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 51729DEA1B9A4F5E004A00EB /* Eureka */;\n\t\t\ttargetProxy = 51729DF71B9A4F5E004A00EB /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin XCBuildConfiguration section */\n\t\t51729DFD1B9A4F5E004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_SWIFT3_OBJC_INFERENCE = Off;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729DFE1B9A4F5E004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tCURRENT_PROJECT_VERSION = 1;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_MISSING_NEWLINE = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_SWIFT3_OBJC_INFERENCE = Off;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t\tVERSION_INFO_PREFIX = \"\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t51729E001B9A4F5E004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tENABLE_BITCODE = YES;\n\t\t\t\tINFOPLIST_FILE = Source/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 5.5.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.Eureka;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729E011B9A4F5E004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tAPPLICATION_EXTENSION_API_ONLY = YES;\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"\";\n\t\t\t\tDEFINES_MODULE = YES;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tDYLIB_COMPATIBILITY_VERSION = 1;\n\t\t\t\tDYLIB_CURRENT_VERSION = 1;\n\t\t\t\tDYLIB_INSTALL_NAME_BASE = \"@rpath\";\n\t\t\t\tENABLE_BITCODE = YES;\n\t\t\t\tINFOPLIST_FILE = Source/Info.plist;\n\t\t\t\tINSTALL_PATH = \"$(LOCAL_LIBRARY_DIR)/Frameworks\";\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tMARKETING_VERSION = 5.5.0;\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.Eureka;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSKIP_INSTALL = YES;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t51729E031B9A4F5E004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Tests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.EurekaTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729E041B9A4F5E004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Tests/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.EurekaTests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t51729DE51B9A4F5E004A00EB /* Build configuration list for PBXProject \"Eureka\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729DFD1B9A4F5E004A00EB /* Debug */,\n\t\t\t\t51729DFE1B9A4F5E004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t51729DFF1B9A4F5E004A00EB /* Build configuration list for PBXNativeTarget \"Eureka\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729E001B9A4F5E004A00EB /* Debug */,\n\t\t\t\t51729E011B9A4F5E004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t51729E021B9A4F5E004A00EB /* Build configuration list for PBXNativeTarget \"EurekaTests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729E031B9A4F5E004A00EB /* Debug */,\n\t\t\t\t51729E041B9A4F5E004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 51729DE21B9A4F5E004A00EB /* Project object */;\n}\n"
  },
  {
    "path": "Eureka.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:Eureka.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Eureka.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Eureka.xcodeproj/xcshareddata/xcschemes/Eureka.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1400\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"51729DEA1B9A4F5E004A00EB\"\n               BuildableName = \"Eureka.framework\"\n               BlueprintName = \"Eureka\"\n               ReferencedContainer = \"container:Eureka.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729DEA1B9A4F5E004A00EB\"\n            BuildableName = \"Eureka.framework\"\n            BlueprintName = \"Eureka\"\n            ReferencedContainer = \"container:Eureka.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"51729DF41B9A4F5E004A00EB\"\n               BuildableName = \"EurekaTests.xctest\"\n               BlueprintName = \"EurekaTests\"\n               ReferencedContainer = \"container:Eureka.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729DEA1B9A4F5E004A00EB\"\n            BuildableName = \"Eureka.framework\"\n            BlueprintName = \"Eureka\"\n            ReferencedContainer = \"container:Eureka.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729DEA1B9A4F5E004A00EB\"\n            BuildableName = \"Eureka.framework\"\n            BlueprintName = \"Eureka\"\n            ReferencedContainer = \"container:Eureka.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "Eureka.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Eureka.playground\">\n   </FileRef>\n   <FileRef\n      location = \"group:Eureka.xcodeproj\">\n   </FileRef>\n   <FileRef\n      location = \"group:Example.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Eureka.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example/EmojiCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"14092\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"14081.1\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" preservesSuperviewLayoutMargins=\"YES\" selectionStyle=\"default\" indentationWidth=\"10\" reuseIdentifier=\"EmojiCell\" textLabel=\"4Kb-XA-Gei\" detailTextLabel=\"b0T-tu-awZ\" rowHeight=\"87\" style=\"IBUITableViewCellStyleSubtitle\" id=\"IUS-Ee-0Ac\" customClass=\"EmojiCell\" customModule=\"Example\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"87\"/>\n            <autoresizingMask key=\"autoresizingMask\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" preservesSuperviewLayoutMargins=\"YES\" insetsLayoutMarginsFromSafeArea=\"NO\" tableViewCell=\"IUS-Ee-0Ac\" id=\"Qbf-AF-gzT\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"86.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"💁🏻\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"4Kb-XA-Gei\">\n                        <rect key=\"frame\" x=\"16\" y=\"15\" width=\"40\" height=\"42\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"35\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <label opaque=\"NO\" multipleTouchEnabled=\"YES\" contentMode=\"left\" insetsLayoutMarginsFromSafeArea=\"NO\" text=\"Subtitle\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" id=\"b0T-tu-awZ\">\n                        <rect key=\"frame\" x=\"16\" y=\"57\" width=\"44\" height=\"14.5\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"12\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n            </tableViewCellContentView>\n            <point key=\"canvasLocation\" x=\"46.5\" y=\"15.5\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "Example/Example/AppDelegate.swift",
    "content": "//  AppDelegate.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport UIKit\n\n@UIApplicationMain\nclass AppDelegate: UIResponder, UIApplicationDelegate {\n\n    var window: UIWindow?\n\n    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {\n        // Take a look at Main.storyboard\n        return true\n    }\n}\n\n"
  },
  {
    "path": "Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon20pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon20pt@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon29pt@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon29pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon29pt@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon40pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon40pt@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"57x57\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"iphone\",\n      \"size\" : \"57x57\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon60pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"appIcon60pt@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"20x20\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"29x29\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"40x40\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"50x50\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"50x50\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"72x72\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"ipad\",\n      \"size\" : \"72x72\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"appIcon76pt@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"appIcon76pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"appIcon83-5pt@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"ios-marketing\",\n      \"size\" : \"1024x1024\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/Eureka.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"Eureka@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/checkedDay.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"checkedDay.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/map_pin.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"map_pin@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"map_pin@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/plus_image.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"plus_image@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"plus_image@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/selected.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"selectedCircle@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"selectedCircle@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/selectedRectangle.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"selectedRectangle@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"selectedRectangle@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/uncheckedDay.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"uncheckedDay.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/unselected.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"unselectedCircle@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"unselectedCircle@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Assets.xcassets/unselectedRectangle.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"unselectedRectangle@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"unselectedRectangle@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Example/Example/Base.lproj/EurekaSectionHeader.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"10112\" systemVersion=\"15D21\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10083\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <view contentMode=\"scaleToFill\" id=\"iN0-l3-epB\" customClass=\"EurekaLogoViewNib\" customModule=\"Example\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"365\" height=\"130\"/>\n            <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n            <subviews>\n                <imageView userInteractionEnabled=\"NO\" contentMode=\"scaleAspectFit\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" image=\"Eureka\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Bjs-Pe-yeM\">\n                    <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"365\" height=\"130\"/>\n                </imageView>\n            </subviews>\n            <constraints>\n                <constraint firstItem=\"Bjs-Pe-yeM\" firstAttribute=\"top\" secondItem=\"iN0-l3-epB\" secondAttribute=\"top\" id=\"4fF-WE-lgN\"/>\n                <constraint firstItem=\"Bjs-Pe-yeM\" firstAttribute=\"leading\" secondItem=\"iN0-l3-epB\" secondAttribute=\"leading\" id=\"BZC-rI-vHR\"/>\n                <constraint firstAttribute=\"trailing\" secondItem=\"Bjs-Pe-yeM\" secondAttribute=\"trailing\" id=\"Evo-0m-78o\"/>\n                <constraint firstAttribute=\"bottom\" secondItem=\"Bjs-Pe-yeM\" secondAttribute=\"bottom\" id=\"Jjg-Ri-jws\"/>\n            </constraints>\n            <nil key=\"simulatedStatusBarMetrics\"/>\n            <nil key=\"simulatedTopBarMetrics\"/>\n            <nil key=\"simulatedBottomBarMetrics\"/>\n            <freeformSimulatedSizeMetrics key=\"simulatedDestinationMetrics\"/>\n            <connections>\n                <outlet property=\"imageView\" destination=\"Bjs-Pe-yeM\" id=\"PfU-lb-bgw\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"430.5\" y=\"158\"/>\n        </view>\n    </objects>\n    <resources>\n        <image name=\"Eureka\" width=\"425\" height=\"125\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "Example/Example/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"14854.2\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" launchScreen=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\" initialViewController=\"01J-lp-oVM\">\n    <device id=\"retina6_1\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"14806.4\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Llm-lL-Icb\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xb3-aO-Qok\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"414\" height=\"896\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Example/Example/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"15505\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useSafeAreas=\"YES\" colorMatched=\"YES\" initialViewController=\"6g3-M9-WkD\">\n    <device id=\"retina5_9\" orientation=\"portrait\" appearance=\"light\"/>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"15510\"/>\n        <capability name=\"Safe area layout guides\" minToolsVersion=\"9.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <scenes>\n        <!--Navigation Accessory Controller-->\n        <scene sceneID=\"KUY-gm-WOC\">\n            <objects>\n                <viewController id=\"qkw-PN-ncD\" customClass=\"NavigationAccessoryController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"aLU-ZA-CPL\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"jQG-xm-oMp\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"NtP-HB-AnI\" firstAttribute=\"bottom\" secondItem=\"jQG-xm-oMp\" secondAttribute=\"bottom\" id=\"8Hm-QB-9Pn\"/>\n                            <constraint firstItem=\"jQG-xm-oMp\" firstAttribute=\"leading\" secondItem=\"NtP-HB-AnI\" secondAttribute=\"leading\" id=\"EHB-bm-9xW\"/>\n                            <constraint firstItem=\"NtP-HB-AnI\" firstAttribute=\"trailing\" secondItem=\"jQG-xm-oMp\" secondAttribute=\"trailing\" id=\"Lsb-Eh-469\"/>\n                            <constraint firstItem=\"jQG-xm-oMp\" firstAttribute=\"top\" secondItem=\"NtP-HB-AnI\" secondAttribute=\"top\" constant=\"-64\" id=\"UrC-SL-ofL\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"NtP-HB-AnI\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"egl-fd-Z6j\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"jQG-xm-oMp\" id=\"DcV-mx-UFW\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"qff-bS-Fd6\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1139.1304347826087\" y=\"-257.8125\"/>\n        </scene>\n        <!--Plain Table View Style Controller-->\n        <scene sceneID=\"8Iv-ww-ibT\">\n            <objects>\n                <viewController id=\"u8Y-1k-1VR\" customClass=\"PlainTableViewStyleController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"aCc-Ey-nD3\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"plain\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"28\" sectionFooterHeight=\"28\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9b5-qK-Oul\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"tqh-Qn-BG6\" firstAttribute=\"bottom\" secondItem=\"9b5-qK-Oul\" secondAttribute=\"bottom\" id=\"GT0-5p-SkJ\"/>\n                            <constraint firstItem=\"tqh-Qn-BG6\" firstAttribute=\"trailing\" secondItem=\"9b5-qK-Oul\" secondAttribute=\"trailing\" id=\"I31-Ya-LHb\"/>\n                            <constraint firstItem=\"9b5-qK-Oul\" firstAttribute=\"top\" secondItem=\"tqh-Qn-BG6\" secondAttribute=\"top\" constant=\"-64\" id=\"NDA-ez-DqV\"/>\n                            <constraint firstItem=\"9b5-qK-Oul\" firstAttribute=\"leading\" secondItem=\"tqh-Qn-BG6\" secondAttribute=\"leading\" id=\"Tc2-VW-AzC\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"tqh-Qn-BG6\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"ZBu-dV-FRu\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"9b5-qK-Oul\" id=\"yv5-t9-NwK\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"U1f-50-jOU\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"505.79710144927537\" y=\"-258.48214285714283\"/>\n        </scene>\n        <!--Eureka! Rows Example-->\n        <scene sceneID=\"bWN-GL-dH9\">\n            <objects>\n                <viewController storyboardIdentifier=\"RowsExampleViewController\" title=\"Eureka! Rows Example\" id=\"iIY-1E-c79\" customClass=\"RowsExampleViewController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"LYQ-fV-apO\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"mHC-X5-7oy\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"788\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"mHC-X5-7oy\" firstAttribute=\"leading\" secondItem=\"WNm-Bu-325\" secondAttribute=\"leading\" id=\"00G-df-Zlp\"/>\n                            <constraint firstItem=\"mHC-X5-7oy\" firstAttribute=\"top\" secondItem=\"WNm-Bu-325\" secondAttribute=\"top\" constant=\"-64\" id=\"IOw-Fs-Oj6\"/>\n                            <constraint firstAttribute=\"bottom\" secondItem=\"mHC-X5-7oy\" secondAttribute=\"bottom\" id=\"beh-j7-CaG\"/>\n                            <constraint firstItem=\"WNm-Bu-325\" firstAttribute=\"trailing\" secondItem=\"mHC-X5-7oy\" secondAttribute=\"trailing\" id=\"kvh-01-UU4\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"WNm-Bu-325\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"ELF-z4-WBZ\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"mHC-X5-7oy\" id=\"hpr-Il-C3d\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"w7K-pv-5uH\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1730.4347826086957\" y=\"-257.8125\"/>\n        </scene>\n        <!--Add Event-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"NativeEventFormViewController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"758\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oJ1-ro-hyM\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"-8\" width=\"375\" height=\"732\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"U5c-nj-u8e\" firstAttribute=\"trailing\" secondItem=\"oJ1-ro-hyM\" secondAttribute=\"trailing\" id=\"XgS-22-Aoo\"/>\n                            <constraint firstItem=\"oJ1-ro-hyM\" firstAttribute=\"top\" secondItem=\"U5c-nj-u8e\" secondAttribute=\"top\" constant=\"-64\" id=\"YSr-Wh-Xyz\"/>\n                            <constraint firstItem=\"U5c-nj-u8e\" firstAttribute=\"bottom\" secondItem=\"oJ1-ro-hyM\" secondAttribute=\"bottom\" id=\"eQ4-u8-vGU\"/>\n                            <constraint firstItem=\"oJ1-ro-hyM\" firstAttribute=\"leading\" secondItem=\"U5c-nj-u8e\" secondAttribute=\"leading\" id=\"uhl-H3-Rce\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"U5c-nj-u8e\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" title=\"Add Event\" id=\"h7i-CH-mmM\">\n                        <barButtonItem key=\"leftBarButtonItem\" systemItem=\"cancel\" id=\"qON-hm-SNY\"/>\n                    </navigationItem>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"oJ1-ro-hyM\" id=\"NSW-Uu-bsz\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"2449.855072463768\" y=\"214.90178571428572\"/>\n        </scene>\n        <!--Navigation Controller-->\n        <scene sceneID=\"nLS-mE-meo\">\n            <objects>\n                <navigationController automaticallyAdjustsScrollViewInsets=\"NO\" id=\"6g3-M9-WkD\" sceneMemberID=\"viewController\">\n                    <toolbarItems/>\n                    <navigationBar key=\"navigationBar\" contentMode=\"scaleToFill\" id=\"37i-zo-mrN\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"44\" width=\"375\" height=\"44\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </navigationBar>\n                    <nil name=\"viewControllers\"/>\n                    <connections>\n                        <segue destination=\"Q34-kO-jVh\" kind=\"relationship\" relationship=\"rootViewController\" id=\"coO-wd-J7b\"/>\n                    </connections>\n                </navigationController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"7Af-Ro-aVc\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"195.94202898550725\" y=\"224.41071428571428\"/>\n        </scene>\n        <!--Examples-->\n        <scene sceneID=\"qdG-dP-VzI\">\n            <objects>\n                <viewController id=\"Q34-kO-jVh\" customClass=\"HomeViewController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ux2-HS-1aH\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"pl1-EZ-WGm\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemBackgroundColor\" cocoaTouchSystemColor=\"whiteColor\"/>\n                        <constraints>\n                            <constraint firstItem=\"cto-dc-jaT\" firstAttribute=\"trailing\" secondItem=\"pl1-EZ-WGm\" secondAttribute=\"trailing\" id=\"7nV-zY-JKN\"/>\n                            <constraint firstItem=\"pl1-EZ-WGm\" firstAttribute=\"leading\" secondItem=\"cto-dc-jaT\" secondAttribute=\"leading\" id=\"VVN-CR-lUf\"/>\n                            <constraint firstItem=\"pl1-EZ-WGm\" firstAttribute=\"top\" secondItem=\"cto-dc-jaT\" secondAttribute=\"top\" constant=\"-64\" id=\"WAd-Vi-yKW\"/>\n                            <constraint firstItem=\"cto-dc-jaT\" firstAttribute=\"bottom\" secondItem=\"pl1-EZ-WGm\" secondAttribute=\"bottom\" id=\"nxj-De-NLD\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"cto-dc-jaT\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" title=\"Examples\" id=\"FWz-Cv-Kdv\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"pl1-EZ-WGm\" id=\"zsO-pM-0A4\"/>\n                        <segue destination=\"iIY-1E-c79\" kind=\"push\" identifier=\"RowsExampleViewControllerSegue\" id=\"zao-qc-znT\"/>\n                        <segue destination=\"3A7-59-k1N\" kind=\"modal\" identifier=\"NativeEventsFormNavigationControllerSegue\" id=\"C5g-Vf-F1k\"/>\n                        <segue destination=\"qkw-PN-ncD\" kind=\"push\" identifier=\"AccesoryViewControllerSegue\" id=\"RnC-5l-00d\"/>\n                        <segue destination=\"fCj-HP-5F1\" kind=\"push\" identifier=\"FieldCustomizationControllerSegue\" id=\"9ui-4G-IO6\"/>\n                        <segue destination=\"tER-SL-iRc\" kind=\"push\" identifier=\"CustomCellsControllerSegue\" id=\"tta-mz-nG3\"/>\n                        <segue destination=\"dNv-jC-9dj\" kind=\"push\" identifier=\"HiddenRowsControllerSegue\" id=\"0ae-09-D0q\"/>\n                        <segue destination=\"pxw-b6-Gas\" kind=\"push\" identifier=\"FormattersControllerSegue\" id=\"ge5-Vi-S0G\"/>\n                        <segue destination=\"WZQ-di-uNi\" kind=\"push\" identifier=\"DisabledRowsControllerSegue\" id=\"eDe-eK-e8n\"/>\n                        <segue destination=\"42E-0V-OKN\" kind=\"push\" identifier=\"InlineRowsControllerSegue\" id=\"sMp-yV-Evw\"/>\n                        <segue destination=\"3b9-rf-NW3\" kind=\"push\" identifier=\"ListSectionsControllerSegue\" id=\"s7W-Vn-beG\"/>\n                        <segue destination=\"1By-iT-GXN\" kind=\"push\" identifier=\"ValidationsControllerSegue\" id=\"e8a-Jy-4iL\"/>\n                        <segue destination=\"1Eh-Nv-AVS\" kind=\"push\" identifier=\"CustomDesignControllerSegue\" id=\"qm6-xE-x5d\"/>\n                        <segue destination=\"qIY-1j-dNf\" kind=\"push\" identifier=\"MultivaluedSectionsControllerSegue\" id=\"HjC-JK-Qvc\"/>\n                        <segue destination=\"u8Y-1k-1VR\" kind=\"push\" identifier=\"PlainTableViewStyleViewControllerSegue\" id=\"kqc-ak-a1R\"/>\n                        <segue destination=\"fc5-sQ-cEm\" kind=\"push\" identifier=\"SwipeActionsControllerSegue\" id=\"AxK-me-pi6\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"Eoz-Jq-Zy9\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"882.60869565217399\" y=\"224.33035714285714\"/>\n        </scene>\n        <!--Field Row Customization Controller-->\n        <scene sceneID=\"W6I-ft-vXN\">\n            <objects>\n                <viewController id=\"fCj-HP-5F1\" customClass=\"FieldRowCustomizationController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"zCX-U4-qfa\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Pne-fE-n6D\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"Cuq-3C-FAE\" firstAttribute=\"bottom\" secondItem=\"Pne-fE-n6D\" secondAttribute=\"bottom\" id=\"41M-Jl-IKE\"/>\n                            <constraint firstItem=\"Pne-fE-n6D\" firstAttribute=\"top\" secondItem=\"Cuq-3C-FAE\" secondAttribute=\"top\" constant=\"-64\" id=\"BD4-qa-mHe\"/>\n                            <constraint firstItem=\"Cuq-3C-FAE\" firstAttribute=\"trailing\" secondItem=\"Pne-fE-n6D\" secondAttribute=\"trailing\" id=\"KUw-yd-say\"/>\n                            <constraint firstItem=\"Pne-fE-n6D\" firstAttribute=\"leading\" secondItem=\"Cuq-3C-FAE\" secondAttribute=\"leading\" id=\"Osr-md-5i1\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"Cuq-3C-FAE\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"9Gs-k4-MI9\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"Pne-fE-n6D\" id=\"MUO-X0-IL3\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"MpW-n9-Kk5\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1773.913043478261\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--Native Event Navigation Controller-->\n        <scene sceneID=\"xGW-9n-a0Q\">\n            <objects>\n                <navigationController automaticallyAdjustsScrollViewInsets=\"NO\" id=\"3A7-59-k1N\" customClass=\"NativeEventNavigationController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <toolbarItems/>\n                    <navigationBar key=\"navigationBar\" contentMode=\"scaleToFill\" id=\"dOa-Gv-ZyO\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"56\"/>\n                        <autoresizingMask key=\"autoresizingMask\"/>\n                    </navigationBar>\n                    <nil name=\"viewControllers\"/>\n                    <connections>\n                        <segue destination=\"BYZ-38-t0r\" kind=\"relationship\" relationship=\"rootViewController\" id=\"JT6-Ui-Yex\"/>\n                    </connections>\n                </navigationController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"1QP-CT-4n8\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1740.2898550724638\" y=\"214.90178571428572\"/>\n        </scene>\n        <!--Disabled Rows Example-->\n        <scene sceneID=\"ABy-XO-E3c\">\n            <objects>\n                <viewController id=\"WZQ-di-uNi\" customClass=\"DisabledRowsExample\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Sc4-2O-AXJ\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Oyg-dY-W55\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"XkN-zT-NEc\" firstAttribute=\"trailing\" secondItem=\"Oyg-dY-W55\" secondAttribute=\"trailing\" id=\"7gn-0e-cZf\"/>\n                            <constraint firstItem=\"Oyg-dY-W55\" firstAttribute=\"top\" secondItem=\"XkN-zT-NEc\" secondAttribute=\"top\" constant=\"-64\" id=\"Gn4-I4-rBc\"/>\n                            <constraint firstItem=\"Oyg-dY-W55\" firstAttribute=\"leading\" secondItem=\"XkN-zT-NEc\" secondAttribute=\"leading\" id=\"Hro-1Y-ulj\"/>\n                            <constraint firstItem=\"XkN-zT-NEc\" firstAttribute=\"bottom\" secondItem=\"Oyg-dY-W55\" secondAttribute=\"bottom\" id=\"c4g-Ey-qFj\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"XkN-zT-NEc\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"4bl-6M-I9c\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"Oyg-dY-W55\" id=\"U4U-2e-K4n\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"jCh-aA-iuT\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"671.01449275362324\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--SwipeActions Example-->\n        <scene sceneID=\"h0m-5n-GTL\">\n            <objects>\n                <viewController title=\"SwipeActions Example\" id=\"fc5-sQ-cEm\" customClass=\"SwipeActionsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"BDe-QW-0vU\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"pZd-Qt-DdU\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"KY1-r2-ar2\"/>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"axy-1K-pFt\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-768.11594202898561\" y=\"1227.4553571428571\"/>\n        </scene>\n        <!--Multivalued Sections Example-->\n        <scene sceneID=\"zbo-bQ-HRw\">\n            <objects>\n                <viewController id=\"qIY-1j-dNf\" customClass=\"MultivaluedSectionsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"pDt-5Z-yLs\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"0u0-ut-SRL\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" title=\"Multivalued Sections Example\" id=\"AEF-L0-dOV\"/>\n                    <connections>\n                        <segue destination=\"3E8-i9-e3P\" kind=\"push\" identifier=\"MultivaluedControllerSegue\" id=\"WPE-k6-DLt\"/>\n                        <segue destination=\"fcN-W7-dk3\" kind=\"push\" identifier=\"MultivaluedOnlyReorderControllerSegue\" id=\"UmF-77-syG\"/>\n                        <segue destination=\"X0Z-sB-j66\" kind=\"push\" identifier=\"MultivaluedOnlyInsertControllerSegue\" id=\"E1b-n9-UAy\"/>\n                        <segue destination=\"duw-cd-ZoW\" kind=\"push\" identifier=\"MultivaluedOnlyDeleteControllerSegue\" id=\"ELX-44-GWI\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"H3o-bj-Hpa\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-149.27536231884059\" y=\"1205.3571428571429\"/>\n        </scene>\n        <!--Custom Design Controller-->\n        <scene sceneID=\"YgN-2q-WXn\">\n            <objects>\n                <viewController id=\"1Eh-Nv-AVS\" customClass=\"CustomDesignController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"4er-sy-2OI\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <viewLayoutGuide key=\"safeArea\" id=\"eSn-2T-5HY\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"jsk-QK-ZNA\"/>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"nBi-85-NX3\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"642.02898550724638\" y=\"1205.3571428571429\"/>\n        </scene>\n        <!--Multivalued Controller-->\n        <scene sceneID=\"q1j-mm-Aje\">\n            <objects>\n                <viewController id=\"3E8-i9-e3P\" customClass=\"MultivaluedController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"ObQ-WF-NaQ\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QYB-0m-3TS\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"0fE-6j-NXZ\" firstAttribute=\"trailing\" secondItem=\"QYB-0m-3TS\" secondAttribute=\"trailing\" id=\"WNq-53-tdD\"/>\n                            <constraint firstItem=\"QYB-0m-3TS\" firstAttribute=\"leading\" secondItem=\"0fE-6j-NXZ\" secondAttribute=\"leading\" id=\"g7B-dV-Rka\"/>\n                            <constraint firstItem=\"QYB-0m-3TS\" firstAttribute=\"top\" secondItem=\"0fE-6j-NXZ\" secondAttribute=\"top\" constant=\"-64\" id=\"hOF-AE-8dp\"/>\n                            <constraint firstItem=\"0fE-6j-NXZ\" firstAttribute=\"bottom\" secondItem=\"QYB-0m-3TS\" secondAttribute=\"bottom\" id=\"iIx-JY-TTE\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"0fE-6j-NXZ\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"JnB-RD-R8g\">\n                        <barButtonItem key=\"rightBarButtonItem\" title=\"Item\" id=\"2jn-dM-TgZ\">\n                            <connections>\n                                <action selector=\"save:\" destination=\"3E8-i9-e3P\" id=\"PAG-gJ-1WR\"/>\n                            </connections>\n                        </barButtonItem>\n                    </navigationItem>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"QYB-0m-3TS\" id=\"iAK-pT-gJd\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"Rb8-YP-WOF\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-1034.0579710144928\" y=\"1705.9151785714284\"/>\n        </scene>\n        <!--Multivalued Only Reorder Controller-->\n        <scene sceneID=\"iCj-Rb-n4P\">\n            <objects>\n                <viewController id=\"fcN-W7-dk3\" customClass=\"MultivaluedOnlyReorderController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"tot-tU-1EY\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"nfL-xs-nks\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"5A2-39-vLN\" firstAttribute=\"trailing\" secondItem=\"nfL-xs-nks\" secondAttribute=\"trailing\" id=\"Q8c-Dl-5N7\"/>\n                            <constraint firstItem=\"nfL-xs-nks\" firstAttribute=\"top\" secondItem=\"5A2-39-vLN\" secondAttribute=\"top\" constant=\"-64\" id=\"X4r-kb-Teo\"/>\n                            <constraint firstItem=\"nfL-xs-nks\" firstAttribute=\"leading\" secondItem=\"5A2-39-vLN\" secondAttribute=\"leading\" id=\"joz-Cm-Ydf\"/>\n                            <constraint firstItem=\"5A2-39-vLN\" firstAttribute=\"bottom\" secondItem=\"nfL-xs-nks\" secondAttribute=\"bottom\" id=\"kKC-5p-SHy\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"5A2-39-vLN\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"oxA-95-cU0\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"nfL-xs-nks\" id=\"iHP-FE-BF2\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iGJ-ZK-Z6q\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-455.07246376811599\" y=\"1704.9107142857142\"/>\n        </scene>\n        <!--Multivalued Only Insert Controller-->\n        <scene sceneID=\"q8U-ZK-3v7\">\n            <objects>\n                <viewController id=\"X0Z-sB-j66\" customClass=\"MultivaluedOnlyInsertController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"NZ2-Ab-KeD\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"9zy-nc-7Mc\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"k5N-q9-Egl\" firstAttribute=\"trailing\" secondItem=\"9zy-nc-7Mc\" secondAttribute=\"trailing\" id=\"5VJ-Q8-2V3\"/>\n                            <constraint firstItem=\"k5N-q9-Egl\" firstAttribute=\"bottom\" secondItem=\"9zy-nc-7Mc\" secondAttribute=\"bottom\" id=\"Tdf-8H-0aa\"/>\n                            <constraint firstItem=\"9zy-nc-7Mc\" firstAttribute=\"top\" secondItem=\"k5N-q9-Egl\" secondAttribute=\"top\" constant=\"-64\" id=\"UTa-RU-N26\"/>\n                            <constraint firstItem=\"9zy-nc-7Mc\" firstAttribute=\"leading\" secondItem=\"k5N-q9-Egl\" secondAttribute=\"leading\" id=\"ocp-Oa-Mno\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"k5N-q9-Egl\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"SZ8-Zk-XSU\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"9zy-nc-7Mc\" id=\"9bF-Fv-4vy\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"qfr-yj-va3\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"123.91304347826087\" y=\"1704.5758928571429\"/>\n        </scene>\n        <!--Multivalued Only Delete Controller-->\n        <scene sceneID=\"cKy-CR-RFW\">\n            <objects>\n                <viewController id=\"duw-cd-ZoW\" customClass=\"MultivaluedOnlyDeleteController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"qXS-6w-zrz\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"zaC-nI-UNK\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"IJ3-lb-fgF\" firstAttribute=\"bottom\" secondItem=\"zaC-nI-UNK\" secondAttribute=\"bottom\" id=\"R1V-hB-AaB\"/>\n                            <constraint firstItem=\"zaC-nI-UNK\" firstAttribute=\"leading\" secondItem=\"IJ3-lb-fgF\" secondAttribute=\"leading\" id=\"hqn-yy-qFx\"/>\n                            <constraint firstItem=\"zaC-nI-UNK\" firstAttribute=\"top\" secondItem=\"IJ3-lb-fgF\" secondAttribute=\"top\" constant=\"-64\" id=\"owB-uD-Hwq\"/>\n                            <constraint firstItem=\"IJ3-lb-fgF\" firstAttribute=\"trailing\" secondItem=\"zaC-nI-UNK\" secondAttribute=\"trailing\" id=\"z8c-hO-WPO\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"IJ3-lb-fgF\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"ZyI-L0-gTH\">\n                        <barButtonItem key=\"rightBarButtonItem\" title=\"Edit\" id=\"TAS-3q-2T6\"/>\n                    </navigationItem>\n                    <connections>\n                        <outlet property=\"editButton\" destination=\"TAS-3q-2T6\" id=\"FjX-jX-Kxn\"/>\n                        <outlet property=\"tableView\" destination=\"zaC-nI-UNK\" id=\"zOS-GW-fdq\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"Cvq-de-G7L\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"689.13043478260875\" y=\"1704.5758928571429\"/>\n        </scene>\n        <!--Custom Cells Controller-->\n        <scene sceneID=\"Fcd-u5-DZ7\">\n            <objects>\n                <viewController id=\"tER-SL-iRc\" customClass=\"CustomCellsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"KoB-Rh-gVx\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"i3R-XH-1m6\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"1qt-sR-yUs\" firstAttribute=\"bottom\" secondItem=\"i3R-XH-1m6\" secondAttribute=\"bottom\" id=\"CUg-Uq-jW1\"/>\n                            <constraint firstItem=\"1qt-sR-yUs\" firstAttribute=\"trailing\" secondItem=\"i3R-XH-1m6\" secondAttribute=\"trailing\" id=\"Sbm-ur-EcB\"/>\n                            <constraint firstItem=\"i3R-XH-1m6\" firstAttribute=\"leading\" secondItem=\"1qt-sR-yUs\" secondAttribute=\"leading\" id=\"U6D-ZR-Vpe\"/>\n                            <constraint firstItem=\"i3R-XH-1m6\" firstAttribute=\"top\" secondItem=\"1qt-sR-yUs\" secondAttribute=\"top\" constant=\"-64\" id=\"sLh-Mo-LAM\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"1qt-sR-yUs\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"BBM-Xs-bLZ\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"i3R-XH-1m6\" id=\"np5-vS-kPb\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"YUF-3z-UZS\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1192.753623188406\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--Hidden Rows Example-->\n        <scene sceneID=\"1aj-zH-uva\">\n            <objects>\n                <viewController id=\"dNv-jC-9dj\" customClass=\"HiddenRowsExample\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"cM0-7f-7CG\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UtE-Tw-uxw\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"Nf2-0o-Oa5\" firstAttribute=\"bottom\" secondItem=\"UtE-Tw-uxw\" secondAttribute=\"bottom\" id=\"fi4-wD-75b\"/>\n                            <constraint firstItem=\"UtE-Tw-uxw\" firstAttribute=\"leading\" secondItem=\"Nf2-0o-Oa5\" secondAttribute=\"leading\" id=\"kuc-E7-BZs\"/>\n                            <constraint firstItem=\"UtE-Tw-uxw\" firstAttribute=\"top\" secondItem=\"Nf2-0o-Oa5\" secondAttribute=\"top\" constant=\"-64\" id=\"o9C-W6-R3d\"/>\n                            <constraint firstItem=\"Nf2-0o-Oa5\" firstAttribute=\"trailing\" secondItem=\"UtE-Tw-uxw\" secondAttribute=\"trailing\" id=\"sUg-aS-lAq\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"Nf2-0o-Oa5\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"DrF-1q-MXF\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"UtE-Tw-uxw\" id=\"Ue5-dY-bbc\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"RaF-uQ-nna\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"136.23188405797103\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--Formatter Example-->\n        <scene sceneID=\"zYf-TU-WuI\">\n            <objects>\n                <viewController id=\"pxw-b6-Gas\" customClass=\"FormatterExample\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"IaL-iT-GN5\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"hQM-hF-1JF\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"JVC-GM-Jex\" firstAttribute=\"bottom\" secondItem=\"hQM-hF-1JF\" secondAttribute=\"bottom\" id=\"CiY-Vk-KTM\"/>\n                            <constraint firstItem=\"hQM-hF-1JF\" firstAttribute=\"leading\" secondItem=\"JVC-GM-Jex\" secondAttribute=\"leading\" id=\"NMz-p3-Mfn\"/>\n                            <constraint firstItem=\"JVC-GM-Jex\" firstAttribute=\"trailing\" secondItem=\"hQM-hF-1JF\" secondAttribute=\"trailing\" id=\"ZrD-qf-f5G\"/>\n                            <constraint firstItem=\"hQM-hF-1JF\" firstAttribute=\"top\" secondItem=\"JVC-GM-Jex\" secondAttribute=\"top\" constant=\"-64\" id=\"dQK-aC-HtE\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"JVC-GM-Jex\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"KgD-DU-iTM\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"hQM-hF-1JF\" id=\"Zby-Zi-Mvx\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"oSy-Z6-fUt\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"-379.71014492753625\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--Inline Rows Controller-->\n        <scene sceneID=\"8X6-E2-OcV\">\n            <objects>\n                <viewController id=\"42E-0V-OKN\" customClass=\"InlineRowsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"fsw-zF-lOT\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dbo-b8-KHY\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"3Se-gK-opy\" firstAttribute=\"bottom\" secondItem=\"dbo-b8-KHY\" secondAttribute=\"bottom\" id=\"7la-3W-uNs\"/>\n                            <constraint firstItem=\"3Se-gK-opy\" firstAttribute=\"trailing\" secondItem=\"dbo-b8-KHY\" secondAttribute=\"trailing\" id=\"BdD-5b-xpl\"/>\n                            <constraint firstItem=\"dbo-b8-KHY\" firstAttribute=\"top\" secondItem=\"3Se-gK-opy\" secondAttribute=\"top\" constant=\"-64\" id=\"MuD-QK-LWW\"/>\n                            <constraint firstItem=\"dbo-b8-KHY\" firstAttribute=\"leading\" secondItem=\"3Se-gK-opy\" secondAttribute=\"leading\" id=\"TXh-mt-vGc\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"3Se-gK-opy\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"v8s-ob-kpd\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"dbo-b8-KHY\" id=\"IJn-wp-dj2\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"YKM-SH-UZU\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"2336.231884057971\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--List Sections Controller-->\n        <scene sceneID=\"edZ-7n-SWy\">\n            <objects>\n                <viewController id=\"3b9-rf-NW3\" customClass=\"ListSectionsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Fhk-b0-B56\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ug4-ix-2ET\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"ug4-ix-2ET\" firstAttribute=\"leading\" secondItem=\"nQw-1f-jR6\" secondAttribute=\"leading\" id=\"2RW-Bg-06M\"/>\n                            <constraint firstItem=\"nQw-1f-jR6\" firstAttribute=\"trailing\" secondItem=\"ug4-ix-2ET\" secondAttribute=\"trailing\" id=\"BeU-yc-cPu\"/>\n                            <constraint firstItem=\"ug4-ix-2ET\" firstAttribute=\"top\" secondItem=\"nQw-1f-jR6\" secondAttribute=\"top\" constant=\"-64\" id=\"Hyd-zf-GVj\"/>\n                            <constraint firstItem=\"nQw-1f-jR6\" firstAttribute=\"bottom\" secondItem=\"ug4-ix-2ET\" secondAttribute=\"bottom\" id=\"w4y-59-zuO\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"nQw-1f-jR6\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"02U-AH-Fg4\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"ug4-ix-2ET\" id=\"P5F-qu-a3F\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"fNU-hH-Dzc\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"2853.6231884057975\" y=\"721.20535714285711\"/>\n        </scene>\n        <!--Validations Controller-->\n        <scene sceneID=\"7OI-m7-xaG\">\n            <objects>\n                <viewController id=\"1By-iT-GXN\" customClass=\"ValidationsController\" customModule=\"Example\" customModuleProvider=\"target\" sceneMemberID=\"viewController\">\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"bOr-53-hGx\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"812\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <tableView clipsSubviews=\"YES\" contentMode=\"scaleToFill\" alwaysBounceVertical=\"YES\" dataMode=\"prototypes\" style=\"grouped\" separatorStyle=\"default\" rowHeight=\"44\" sectionHeaderHeight=\"18\" sectionFooterHeight=\"18\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Sbj-p4-BRo\">\n                                <rect key=\"frame\" x=\"0.0\" y=\"24\" width=\"375\" height=\"754\"/>\n                                <color key=\"backgroundColor\" cocoaTouchSystemColor=\"groupTableViewBackgroundColor\"/>\n                            </tableView>\n                        </subviews>\n                        <color key=\"backgroundColor\" systemColor=\"systemGroupedBackgroundColor\" red=\"0.94901960780000005\" green=\"0.94901960780000005\" blue=\"0.96862745100000003\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"jw6-Ll-9B5\" firstAttribute=\"trailing\" secondItem=\"Sbj-p4-BRo\" secondAttribute=\"trailing\" id=\"8Mu-6X-XGE\"/>\n                            <constraint firstItem=\"jw6-Ll-9B5\" firstAttribute=\"bottom\" secondItem=\"Sbj-p4-BRo\" secondAttribute=\"bottom\" id=\"Lvu-PG-w11\"/>\n                            <constraint firstItem=\"Sbj-p4-BRo\" firstAttribute=\"top\" secondItem=\"jw6-Ll-9B5\" secondAttribute=\"top\" constant=\"-64\" id=\"Njp-iN-LXg\"/>\n                            <constraint firstItem=\"Sbj-p4-BRo\" firstAttribute=\"leading\" secondItem=\"jw6-Ll-9B5\" secondAttribute=\"leading\" id=\"ZaJ-hJ-M3n\"/>\n                        </constraints>\n                        <viewLayoutGuide key=\"safeArea\" id=\"jw6-Ll-9B5\"/>\n                    </view>\n                    <navigationItem key=\"navigationItem\" id=\"Tcp-rc-Ewq\"/>\n                    <connections>\n                        <outlet property=\"tableView\" destination=\"Sbj-p4-BRo\" id=\"BPM-PB-QbX\"/>\n                    </connections>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"L7e-b8-eJH\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"1244.9275362318842\" y=\"1227.4553571428571\"/>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "Example/Example/Base.lproj/WeekDaysCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"8191\" systemVersion=\"14F27\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"8154\"/>\n        <capability name=\"Constraints to layout margins\" minToolsVersion=\"6.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell contentMode=\"scaleToFill\" selectionStyle=\"default\" indentationWidth=\"10\" rowHeight=\"61\" id=\"piA-L5-eiN\" customClass=\"WeekDayCell\" customModule=\"Example\" customModuleProvider=\"target\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"382\" height=\"61\"/>\n            <autoresizingMask key=\"autoresizingMask\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"piA-L5-eiN\" id=\"Yr6-3E-keb\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"382\" height=\"60\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" misplaced=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"ZAg-Me-yKR\">\n                        <rect key=\"frame\" x=\"8\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"S\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <state key=\"selected\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"VSl-nH-cWo\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"UjQ-Cw-7wH\" userLabel=\"separator 1\">\n                        <rect key=\"frame\" x=\"59\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"K3N-3h-MZr\"/>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"rqR-J5-JEQ\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"N3w-qP-kRZ\">\n                        <rect key=\"frame\" x=\"60\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"M\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"FaQ-oB-Nkl\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"kwc-0w-V51\" userLabel=\"separator 2\">\n                        <rect key=\"frame\" x=\"112\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"3mE-sT-ql1\"/>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"DIe-f7-hxR\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" misplaced=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cPl-47-rS8\">\n                        <rect key=\"frame\" x=\"113\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"T\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"4vk-5n-jge\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"EiN-2p-Oig\" userLabel=\"separator 3\">\n                        <rect key=\"frame\" x=\"164\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"EqQ-Te-SQd\"/>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"JyW-GC-0A7\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" misplaced=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"6iC-Cl-RyI\">\n                        <rect key=\"frame\" x=\"166\" y=\"0.0\" width=\"51\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"W\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"oO1-zj-XRv\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" misplaced=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"bRc-5e-QAH\" userLabel=\"separator 4\">\n                        <rect key=\"frame\" x=\"216\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"Pxp-Ee-q5x\"/>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"W9F-iR-Leh\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" misplaced=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"eTo-Ip-reh\">\n                        <rect key=\"frame\" x=\"217\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"T\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"SkQ-0a-9Fy\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"dHj-rj-mjh\" userLabel=\"separator 5\">\n                        <rect key=\"frame\" x=\"269\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"h5U-x0-9nJ\"/>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"uKJ-Sn-OXS\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"Wjb-tu-QEo\">\n                        <rect key=\"frame\" x=\"270\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"F\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"9A8-9a-SGG\"/>\n                        </connections>\n                    </button>\n                    <view contentMode=\"scaleToFill\" misplaced=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"L7g-lu-boa\" userLabel=\"separator 6\">\n                        <rect key=\"frame\" x=\"321\" y=\"10\" width=\"1\" height=\"40\"/>\n                        <animations/>\n                        <color key=\"backgroundColor\" white=\"0.66666666666666663\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"width\" constant=\"1\" id=\"81t-Xh-wZT\"/>\n                            <constraint firstAttribute=\"height\" constant=\"40\" id=\"Qr7-X4-anj\"/>\n                        </constraints>\n                    </view>\n                    <button opaque=\"NO\" contentMode=\"scaleToFill\" misplaced=\"YES\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" lineBreakMode=\"middleTruncation\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"LNf-b4-GYP\">\n                        <rect key=\"frame\" x=\"322\" y=\"0.0\" width=\"52\" height=\"60\"/>\n                        <animations/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"16\"/>\n                        <state key=\"normal\" title=\"S\">\n                            <color key=\"titleColor\" cocoaTouchSystemColor=\"darkTextColor\"/>\n                            <color key=\"titleShadowColor\" white=\"0.5\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        </state>\n                        <connections>\n                            <action selector=\"dayTapped:\" destination=\"piA-L5-eiN\" eventType=\"touchUpInside\" id=\"I4k-Ho-KxE\"/>\n                        </connections>\n                    </button>\n                </subviews>\n                <animations/>\n                <constraints>\n                    <constraint firstItem=\"LNf-b4-GYP\" firstAttribute=\"leading\" secondItem=\"L7g-lu-boa\" secondAttribute=\"trailing\" id=\"0fo-jx-Csm\"/>\n                    <constraint firstItem=\"6iC-Cl-RyI\" firstAttribute=\"centerY\" secondItem=\"eTo-Ip-reh\" secondAttribute=\"centerY\" id=\"0uH-JF-ybH\"/>\n                    <constraint firstItem=\"eTo-Ip-reh\" firstAttribute=\"centerY\" secondItem=\"Wjb-tu-QEo\" secondAttribute=\"centerY\" id=\"1YJ-rb-OaE\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"ZAg-Me-yKR\" secondAttribute=\"bottom\" id=\"1k4-7I-heJ\"/>\n                    <constraint firstItem=\"kwc-0w-V51\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"6Wt-56-rnK\"/>\n                    <constraint firstItem=\"bRc-5e-QAH\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"6qd-rB-kSj\"/>\n                    <constraint firstItem=\"cPl-47-rS8\" firstAttribute=\"width\" secondItem=\"6iC-Cl-RyI\" secondAttribute=\"width\" id=\"7FE-J3-Edw\"/>\n                    <constraint firstItem=\"ZAg-Me-yKR\" firstAttribute=\"leading\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"leadingMargin\" id=\"8Nq-Rj-q19\"/>\n                    <constraint firstItem=\"6iC-Cl-RyI\" firstAttribute=\"height\" secondItem=\"eTo-Ip-reh\" secondAttribute=\"height\" id=\"8g1-v4-nx0\"/>\n                    <constraint firstAttribute=\"trailingMargin\" secondItem=\"LNf-b4-GYP\" secondAttribute=\"trailing\" id=\"8ld-NW-TWG\"/>\n                    <constraint firstItem=\"eTo-Ip-reh\" firstAttribute=\"height\" secondItem=\"Wjb-tu-QEo\" secondAttribute=\"height\" id=\"9sP-NP-Hr6\"/>\n                    <constraint firstItem=\"kwc-0w-V51\" firstAttribute=\"leading\" secondItem=\"N3w-qP-kRZ\" secondAttribute=\"trailing\" id=\"ASB-hZ-lyM\"/>\n                    <constraint firstItem=\"EiN-2p-Oig\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"Ahe-jK-GJV\"/>\n                    <constraint firstItem=\"eTo-Ip-reh\" firstAttribute=\"leading\" secondItem=\"bRc-5e-QAH\" secondAttribute=\"trailing\" id=\"Epj-Rj-gWF\"/>\n                    <constraint firstItem=\"Wjb-tu-QEo\" firstAttribute=\"height\" secondItem=\"LNf-b4-GYP\" secondAttribute=\"height\" id=\"Ff1-qP-IsO\"/>\n                    <constraint firstItem=\"N3w-qP-kRZ\" firstAttribute=\"height\" secondItem=\"cPl-47-rS8\" secondAttribute=\"height\" id=\"I3w-At-X2i\"/>\n                    <constraint firstItem=\"dHj-rj-mjh\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"JxY-fD-idN\"/>\n                    <constraint firstItem=\"bRc-5e-QAH\" firstAttribute=\"leading\" secondItem=\"6iC-Cl-RyI\" secondAttribute=\"trailing\" id=\"TYV-f4-M6e\"/>\n                    <constraint firstItem=\"UjQ-Cw-7wH\" firstAttribute=\"leading\" secondItem=\"ZAg-Me-yKR\" secondAttribute=\"trailing\" id=\"UJC-9V-Cd5\"/>\n                    <constraint firstItem=\"L7g-lu-boa\" firstAttribute=\"leading\" secondItem=\"Wjb-tu-QEo\" secondAttribute=\"trailing\" id=\"VD9-6D-KvT\"/>\n                    <constraint firstItem=\"Wjb-tu-QEo\" firstAttribute=\"centerY\" secondItem=\"LNf-b4-GYP\" secondAttribute=\"centerY\" id=\"WlU-5s-b4D\"/>\n                    <constraint firstItem=\"Wjb-tu-QEo\" firstAttribute=\"leading\" secondItem=\"dHj-rj-mjh\" secondAttribute=\"trailing\" id=\"Yk2-Af-jOs\"/>\n                    <constraint firstItem=\"ZAg-Me-yKR\" firstAttribute=\"top\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"top\" id=\"aIH-xh-6EK\"/>\n                    <constraint firstItem=\"cPl-47-rS8\" firstAttribute=\"centerY\" secondItem=\"6iC-Cl-RyI\" secondAttribute=\"centerY\" id=\"aqH-x8-tOF\"/>\n                    <constraint firstItem=\"ZAg-Me-yKR\" firstAttribute=\"width\" secondItem=\"N3w-qP-kRZ\" secondAttribute=\"width\" id=\"bt9-yU-qnt\"/>\n                    <constraint firstItem=\"N3w-qP-kRZ\" firstAttribute=\"leading\" secondItem=\"UjQ-Cw-7wH\" secondAttribute=\"trailing\" id=\"c66-Xu-mQL\"/>\n                    <constraint firstItem=\"dHj-rj-mjh\" firstAttribute=\"leading\" secondItem=\"eTo-Ip-reh\" secondAttribute=\"trailing\" id=\"chy-b8-EdK\"/>\n                    <constraint firstItem=\"6iC-Cl-RyI\" firstAttribute=\"leading\" secondItem=\"EiN-2p-Oig\" secondAttribute=\"trailing\" id=\"gUc-Sa-nVM\"/>\n                    <constraint firstItem=\"L7g-lu-boa\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"hvJ-oj-w92\"/>\n                    <constraint firstItem=\"Wjb-tu-QEo\" firstAttribute=\"width\" secondItem=\"LNf-b4-GYP\" secondAttribute=\"width\" id=\"ivo-7Y-SmP\"/>\n                    <constraint firstItem=\"ZAg-Me-yKR\" firstAttribute=\"height\" secondItem=\"N3w-qP-kRZ\" secondAttribute=\"height\" id=\"mrw-x5-waX\"/>\n                    <constraint firstItem=\"EiN-2p-Oig\" firstAttribute=\"leading\" secondItem=\"cPl-47-rS8\" secondAttribute=\"trailing\" id=\"oZ4-Px-RGe\"/>\n                    <constraint firstItem=\"UjQ-Cw-7wH\" firstAttribute=\"centerY\" secondItem=\"Yr6-3E-keb\" secondAttribute=\"centerY\" id=\"qXM-7h-bDi\"/>\n                    <constraint firstItem=\"ZAg-Me-yKR\" firstAttribute=\"centerY\" secondItem=\"N3w-qP-kRZ\" secondAttribute=\"centerY\" id=\"r9V-i5-aLY\"/>\n                    <constraint firstItem=\"N3w-qP-kRZ\" firstAttribute=\"width\" secondItem=\"cPl-47-rS8\" secondAttribute=\"width\" id=\"rzb-2W-aN1\"/>\n                    <constraint firstItem=\"cPl-47-rS8\" firstAttribute=\"height\" secondItem=\"6iC-Cl-RyI\" secondAttribute=\"height\" id=\"sWf-oo-N8w\"/>\n                    <constraint firstItem=\"eTo-Ip-reh\" firstAttribute=\"width\" secondItem=\"Wjb-tu-QEo\" secondAttribute=\"width\" id=\"w7P-NJ-TWy\"/>\n                    <constraint firstItem=\"cPl-47-rS8\" firstAttribute=\"leading\" secondItem=\"kwc-0w-V51\" secondAttribute=\"trailing\" id=\"wiy-6c-zng\"/>\n                    <constraint firstItem=\"N3w-qP-kRZ\" firstAttribute=\"centerY\" secondItem=\"cPl-47-rS8\" secondAttribute=\"centerY\" id=\"xj5-Uv-mZj\"/>\n                    <constraint firstItem=\"6iC-Cl-RyI\" firstAttribute=\"width\" secondItem=\"eTo-Ip-reh\" secondAttribute=\"width\" id=\"zRG-mE-VLw\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <animations/>\n            <connections>\n                <outlet property=\"fridayButton\" destination=\"Wjb-tu-QEo\" id=\"AcP-Qg-i9P\"/>\n                <outlet property=\"mondayButton\" destination=\"N3w-qP-kRZ\" id=\"u3A-mt-EKd\"/>\n                <outlet property=\"saturdayButton\" destination=\"LNf-b4-GYP\" id=\"TeM-3b-B1Z\"/>\n                <outlet property=\"sundayButton\" destination=\"ZAg-Me-yKR\" id=\"6yQ-QG-SlK\"/>\n                <outlet property=\"thursdayButton\" destination=\"eTo-Ip-reh\" id=\"Dxi-hi-oBK\"/>\n                <outlet property=\"tuesdayButton\" destination=\"cPl-47-rS8\" id=\"wIn-mO-cUx\"/>\n                <outlet property=\"wednesdayButton\" destination=\"6iC-Cl-RyI\" id=\"GQe-Oy-pcd\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"296\" y=\"222.5\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "Example/Example/Controllers/CustomCellsViewController.swift",
    "content": "//\n//  CustomCellsViewController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n//MARK: Custom Cells Example\n\nclass CustomCellsController : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form +++\n            Section() {\n                var header = HeaderFooterView<EurekaLogoViewNib>(.nibFile(name: \"EurekaSectionHeader\", bundle: nil))\n                header.onSetupView = { (view, section) -> () in\n                    view.imageView.alpha = 0;\n                    UIView.animate(withDuration: 2.0, animations: { [weak view] in\n                        view?.imageView.alpha = 1\n                    })\n                    view.layer.transform = CATransform3DMakeScale(0.9, 0.9, 1)\n                    UIView.animate(withDuration: 1.0, animations: { [weak view] in\n                        view?.layer.transform = CATransform3DIdentity\n                    })\n                }\n                $0.header = header\n            }\n            +++ Section(\"WeekDay cell\")\n\n            <<< WeekDayRow(){\n                $0.value = [.monday, .wednesday, .friday]\n            }\n\n            <<< TextFloatLabelRow() {\n                $0.title = \"Float Label Row, type something to see..\"\n            }\n\n            <<< IntFloatLabelRow() {\n                $0.title = \"Float Label Row, type something to see..\"\n        }\n    }\n\n}\n\nclass EurekaLogoViewNib: UIView {\n\n    @IBOutlet weak var imageView: UIImageView!\n\n    required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/CustomDesignController.swift",
    "content": "//\n//  CustomDesignController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass CustomDesignController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form +++\n            Section()\n            <<< SwitchRow() {\n                $0.cellProvider = CellProvider<SwitchCell>(nibName: \"SwitchCell\", bundle: Bundle.main)\n            }.cellSetup { (cell, row) in\n                cell.height = { 67 }\n            }\n\n            <<< DatePickerRow() {\n                $0.cellProvider = CellProvider<DatePickerCell>(nibName: \"DatePickerCell\", bundle: Bundle.main)\n            }.cellSetup { (cell, row) in\n                cell.height = { 345 }\n            }\n\n            <<< TextRow() {\n                $0.cellProvider = CellProvider<TextCell>(nibName: \"TextCell\", bundle: Bundle.main)\n                }.cellSetup { (cell, row) in\n                    cell.height = { 199 }\n                }\n                .onChange { row in\n                    if let textView = row.cell.viewWithTag(99) as? UITextView {\n                        textView.text = row.cell.textField.text\n                    }\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/DisabledRowsExample.swift",
    "content": "//\n//  DisabledRowsExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass DisabledRowsExample : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form = Section()\n\n            <<< SegmentedRow<String>(\"segments\"){\n                $0.options = [\"Enabled\", \"Disabled\"]\n                $0.value = \"Disabled\"\n            }\n\n            <<< TextRow(){\n                $0.title = \"choose enabled, disable above...\"\n                $0.disabled = \"$segments = 'Disabled'\"\n            }\n\n            <<< SwitchRow(\"Disable Next Section?\"){\n                $0.title = $0.tag\n                $0.disabled = \"$segments = 'Disabled'\"\n            }\n\n            +++ Section()\n\n            <<< TextRow() {\n                $0.title = \"Gonna be disabled soon..\"\n                $0.disabled = Eureka.Condition.function([\"Disable Next Section?\"], { (form) -> Bool in\n                    let row: SwitchRow! = form.rowBy(tag: \"Disable Next Section?\")\n                    return row.value ?? false\n                })\n            }\n\n            +++ Section()\n\n            <<< SegmentedRow<String>(){\n                $0.options = [\"Always Disabled\"]\n                $0.disabled = true\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/FieldRowCustomizationController.swift",
    "content": "//\n//  FieldRowCustomizationController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass FieldRowCustomizationController : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form +++\n            Section(header: \"Default field rows\", footer: \"Rows with title have a right-aligned text field.\\nRows without title have a left-aligned text field.\\nBut this can be changed...\")\n\n            <<< NameRow() {\n                $0.title = \"Your name:\"\n                $0.placeholder = \"(right alignment)\"\n                }\n                .cellSetup { cell, row in\n                    cell.imageView?.image = UIImage(named: \"plus_image\")\n            }\n\n            <<< NameRow() {\n                $0.placeholder = \"Name (left alignment)\"\n                }\n                .cellSetup { cell, row in\n                    cell.imageView?.image = UIImage(named: \"plus_image\")\n            }\n\n            +++ Section(\"Customized Alignment\")\n\n            <<< NameRow() {\n                $0.title = \"Your name:\"\n                }.cellUpdate { cell, row in\n                    cell.textField.textAlignment = .left\n                    cell.textField.placeholder = \"(left alignment)\"\n            }\n\n            <<< NameRow().cellUpdate { cell, row in\n                cell.textField.textAlignment = .right\n                cell.textField.placeholder = \"Name (right alignment)\"\n            }\n\n            +++ Section(header: \"Customized Text field width\", footer: \"Eureka allows us to set up a specific UITextField width using textFieldPercentage property. In the section above we have also right aligned the textLabels.\")\n\n            <<< NameRow() {\n                $0.title = \"Title\"\n                $0.titlePercentage = 0.4\n                $0.placeholder = \"textFieldPercentage = 0.6\"\n                }\n                .cellUpdate {\n                    $1.cell.textField.textAlignment = .left\n                    $1.cell.textLabel?.textAlignment = .right\n            }\n            <<< NameRow() {\n                $0.title = \"Another Title\"\n                $0.titlePercentage = 0.4\n                $0.placeholder = \"textFieldPercentage = 0.6\"\n                }\n                .cellUpdate {\n                    $1.cell.textField.textAlignment = .left\n                    $1.cell.textLabel?.textAlignment = .right\n            }\n            <<< NameRow() {\n                $0.title = \"One more\"\n                $0.titlePercentage = 0.3\n                $0.placeholder = \"textFieldPercentage = 0.7\"\n                }\n                .cellUpdate {\n                    $1.cell.textField.textAlignment = .left\n                    $1.cell.textLabel?.textAlignment = .right\n            }\n\n            +++ Section(\"TextAreaRow\")\n\n            <<< TextAreaRow() {\n                $0.placeholder = \"TextAreaRow\"\n                $0.textAreaHeight = .dynamic(initialTextViewHeight: 110)\n        }\n            <<< TextAreaRow() {\n                $0.value = \"You also have scrollable read only textAreaRows! I have to write a big text so you will be able to scroll a lot and see that this row is scrollable. I think it is a good idea to insert a Lorem Ipsum here: Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla ac odio consectetur, faucibus elit at, congue dolor. Duis quis magna eu ante egestas laoreet. Vivamus ultricies tristique porttitor. Proin viverra sem non turpis molestie, volutpat facilisis justo rutrum. Nulla eget commodo ligula. Aliquam lobortis lobortis justo id fermentum. Sed sit amet elit eu ipsum ultricies porttitor et sed justo. Fusce id mi aliquam, iaculis odio ac, tempus sem. Aenean in eros imperdiet, euismod lacus vitae, mattis nulla. Praesent ornare sem vitae ornare efficitur. Nullam dictum tortor a tortor vestibulum pharetra. Donec sollicitudin varius fringilla. Praesent posuere fringilla tristique. Aliquam dapibus vel nisi in sollicitudin. In eu ligula arcu.\"\n                $0.textAreaMode = .readOnly\n                $0.textAreaHeight = .fixed(cellHeight: 110)\n        }\n\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/FormatterExample.swift",
    "content": "//\n//  FormatterExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass FormatterExample : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form +++ Section(\"Number formatters\")\n            <<< DecimalRow(){\n                $0.useFormatterDuringInput = true\n                $0.title = \"Currency style\"\n                $0.value = 2015\n                let formatter = CurrencyFormatter()\n                formatter.locale = .current\n                formatter.numberStyle = .currency\n                $0.formatter = formatter\n            }\n            <<< DecimalRow(){\n                $0.title = \"Scientific style\"\n                $0.value = 2015\n                let formatter = NumberFormatter()\n                formatter.locale = .current\n                formatter.numberStyle = .scientific\n                $0.formatter = formatter\n            }\n            <<< IntRow(){\n                $0.title = \"Spell out style\"\n                $0.value = 2015\n                let formatter = NumberFormatter()\n                formatter.locale = .current\n                formatter.numberStyle = .spellOut\n                $0.formatter = formatter\n            }\n            +++ Section(\"Date formatters\")\n            <<< DateRow(){\n                $0.title = \"Short style\"\n                $0.value = Date()\n                let formatter = DateFormatter()\n                formatter.locale = .current\n                formatter.dateStyle = .short\n                $0.dateFormatter = formatter\n            }\n            <<< DateRow(){\n                $0.title = \"Long style\"\n                $0.value = Date()\n                let formatter = DateFormatter()\n                formatter.locale = .current\n                formatter.dateStyle = .long\n                $0.dateFormatter = formatter\n            }\n            +++ Section(\"Other formatters\")\n            <<< DecimalRow(){\n                $0.title = \"Energy: Jules to calories\"\n                $0.value = 100.0\n                let formatter = EnergyFormatter()\n                $0.formatter = formatter\n            }\n            <<< IntRow(){\n                $0.title = \"Weight: Kg to lb\"\n                $0.value = 1000\n                $0.formatter = MassFormatter()\n        }\n    }\n\n    class CurrencyFormatter : NumberFormatter, FormatterProtocol {\n        override func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, range rangep: UnsafeMutablePointer<NSRange>?) throws {\n            guard obj != nil else { return }\n            var str = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: \"\")\n            if !string.isEmpty, numberStyle == .currency && !string.contains(currencySymbol) {\n                // Check if the currency symbol is at the last index\n                if let formattedNumber = self.string(from: 1), String(formattedNumber[formattedNumber.index(before: formattedNumber.endIndex)...]) == currencySymbol {\n                    // This means the user has deleted the currency symbol. We cut the last number and then add the symbol automatically\n                    str = String(str[..<str.index(before: str.endIndex)])\n\n                }\n            }\n            obj?.pointee = NSNumber(value: (Double(str) ?? 0.0)/Double(pow(10.0, Double(minimumFractionDigits))))\n        }\n\n        func getNewPosition(forPosition position: UITextPosition, inTextInput textInput: UITextInput, oldValue: String?, newValue: String?) -> UITextPosition {\n            return textInput.position(from: position, offset:((newValue?.count ?? 0) - (oldValue?.count ?? 0))) ?? position\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/HiddenRowsExample.swift",
    "content": "//\n//  HiddenRowsExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass HiddenRowsExample : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        TextRow.defaultCellUpdate = { cell, row in\n            cell.textLabel?.font = UIFont.italicSystemFont(ofSize: 12)\n        }\n\n        form = Section(\"What do you want to talk about:\")\n            <<< SegmentedRow<String>(\"segments\"){\n                $0.options = [\"Sport\", \"Music\", \"Films\"]\n                $0.value = \"Films\"\n            }\n            +++ Section(){\n                $0.tag = \"sport_s\"\n                $0.hidden = \"$segments != 'Sport'\" // .Predicate(NSPredicate(format: \"$segments != 'Sport'\"))\n            }\n            <<< TextRow(){\n                $0.title = \"Which is your favourite soccer player?\"\n            }\n\n            <<< TextRow(){\n                $0.title = \"Which is your favourite coach?\"\n            }\n\n            <<< TextRow(){\n                $0.title = \"Which is your favourite team?\"\n            }\n\n            +++ Section(){\n                $0.tag = \"music_s\"\n                $0.hidden = \"$segments != 'Music'\"\n            }\n            <<< TextRow(){\n                $0.title = \"Which music style do you like most?\"\n            }\n\n            <<< TextRow(){\n                $0.title = \"Which is your favourite singer?\"\n            }\n            <<< TextRow(){\n                $0.title = \"How many CDs have you got?\"\n            }\n\n            +++ Section(){\n                $0.tag = \"films_s\"\n                $0.hidden = \"$segments != 'Films'\"\n            }\n            <<< TextRow(){\n                $0.title = \"Which is your favourite actor?\"\n            }\n\n            <<< TextRow(){\n                $0.title = \"Which is your favourite film?\"\n            }\n\n            +++ Section()\n\n            <<< SwitchRow(\"Show Next Row\"){\n                $0.title = $0.tag\n            }\n            <<< SwitchRow(\"Show Next Section\"){\n                $0.title = $0.tag\n                $0.hidden = .function([\"Show Next Row\"], { form -> Bool in\n                    let row: RowOf<Bool>! = form.rowBy(tag: \"Show Next Row\")\n                    return row.value ?? false == false\n                })\n            }\n\n            +++ Section(footer: \"This section is shown only when 'Show Next Row' switch is enabled\"){\n                $0.hidden = .function([\"Show Next Section\"], { form -> Bool in\n                    let row: RowOf<Bool>! = form.rowBy(tag: \"Show Next Section\")\n                    return row.value ?? false == false\n                })\n            }\n            <<< TextRow() {\n                $0.placeholder = \"Gonna dissapear soon!!\"\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/InlineRowsExample.swift",
    "content": "//\n//  InlineRowsExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass InlineRowsController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form.inlineRowHideOptions = InlineRowHideOptions.AnotherInlineRowIsShown.union(.FirstResponderChanges)\n\n        form\n\n            +++ Section(\"Automatically Hide Inline Rows?\")\n\n            <<< SwitchRow() {\n                $0.title = \"Hides when another inline row is shown\"\n                $0.value = true\n                }\n                .onChange { [weak form] in\n                    if $0.value == true {\n                        form?.inlineRowHideOptions = form?.inlineRowHideOptions?.union(.AnotherInlineRowIsShown)\n                    }\n                    else {\n                        form?.inlineRowHideOptions = form?.inlineRowHideOptions?.subtracting(.AnotherInlineRowIsShown)\n                    }\n            }\n\n            <<< SwitchRow() {\n                $0.title = \"Hides when the First Responder changes\"\n                $0.value = true\n                }\n                .onChange { [weak form] in\n                    if $0.value == true {\n                        form?.inlineRowHideOptions = form?.inlineRowHideOptions?.union(.FirstResponderChanges)\n                    }\n                    else {\n                        form?.inlineRowHideOptions = form?.inlineRowHideOptions?.subtracting(.FirstResponderChanges)\n                    }\n            }\n\n            +++ Section()\n\n            <<< DateInlineRow() {\n                $0.title = \"DateInlineRow\"\n                $0.value = Date()\n            }\n\n            <<< TimeInlineRow(){\n                $0.title = \"TimeInlineRow\"\n                $0.value = Date()\n            }\n\n            <<< DateTimeInlineRow(){\n                $0.title = \"DateTimeInlineRow\"\n                $0.value = Date()\n            }\n\n            <<< CountDownInlineRow(){\n                $0.title = \"CountDownInlineRow\"\n                var dateComp = DateComponents()\n                dateComp.hour = 18\n                dateComp.minute = 33\n                dateComp.timeZone = TimeZone.current\n                $0.value = Calendar.current.date(from: dateComp)\n            }\n\n            +++ Section(\"Generic inline picker\")\n\n            <<< PickerInlineRow<Date>(\"PickerInlineRow\") { (row : PickerInlineRow<Date>) -> Void in\n                row.title = row.tag\n                row.displayValueFor = { (rowValue: Date?) in\n                    return rowValue.map { \"Year \\(Calendar.current.component(.year, from: $0))\" }\n                }\n                row.options = []\n                var date = Date()\n                for _ in 1...10{\n                    row.options.append(date)\n                    date = date.addingTimeInterval(60*60*24*365)\n                }\n                row.value = row.options[0]\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/ListSectionsController.swift",
    "content": "//\n//  ListSectionsController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass ListSectionsController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        let continents = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\n\n        form +++ SelectableSection<ImageCheckRow<String>>() { section in\n            section.header = HeaderFooterView(title: \"Where do you live?\")\n        }\n\n        for option in continents {\n            form.last! <<< ImageCheckRow<String>(option){ lrow in\n                lrow.title = option\n                lrow.selectableValue = option\n                lrow.value = nil\n            }\n        }\n\n        let oceans = [\"Arctic\", \"Atlantic\", \"Indian\", \"Pacific\", \"Southern\"]\n\n        form +++ SelectableSection<ImageCheckRow<String>>(\"And which of the following oceans have you taken a bath in?\", selectionType: .multipleSelection)\n        for option in oceans {\n            form.last! <<< ImageCheckRow<String>(option){ lrow in\n                lrow.title = option\n                lrow.selectableValue = option\n                lrow.value = nil\n                }.cellSetup { cell, _ in\n                    cell.trueImage = UIImage(named: \"selectedRectangle\")!\n                    cell.falseImage = UIImage(named: \"unselectedRectangle\")!\n                    cell.accessoryType = .checkmark\n            }\n        }\n    }\n\n    override func valueHasBeenChanged(for row: BaseRow, oldValue: Any?, newValue: Any?) {\n        if row.section === form[0] {\n            print(\"Single Selection:\\((row.section as! SelectableSection<ImageCheckRow<String>>).selectedRow()?.baseValue ?? \"No row selected\")\")\n        }\n        else if row.section === form[1] {\n            print(\"Mutiple Selection:\\((row.section as! SelectableSection<ImageCheckRow<String>>).selectedRows().map({$0.baseValue}))\")\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/MultivaluedExamples.swift",
    "content": "//\n//  MultivaluedSectionsController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass MultivaluedSectionsController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        title = \"Multivalued examples\"\n        form +++\n            Section(\"Multivalued examples\")\n            <<< ButtonRow(){\n                $0.title = \"Multivalued Sections\"\n                $0.presentationMode = .segueName(segueName: \"MultivaluedControllerSegue\", onDismiss: nil)\n            }\n            <<< ButtonRow(){\n                $0.title = \"Multivalued Only Reorder\"\n                $0.presentationMode = .segueName(segueName: \"MultivaluedOnlyReorderControllerSegue\", onDismiss: nil)\n            }\n            <<< ButtonRow(){\n                $0.title = \"Multivalued Only Insert\"\n                $0.presentationMode = .segueName(segueName: \"MultivaluedOnlyInsertControllerSegue\", onDismiss: nil)\n            }\n            <<< ButtonRow(){\n                $0.title = \"Multivalued Only Delete\"\n                $0.presentationMode = .segueName(segueName: \"MultivaluedOnlyDeleteControllerSegue\", onDismiss: nil)\n        }\n    }\n\n}\n\nclass MultivaluedController: FormViewController {\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        title = \"Multivalued Examples\"\n        form +++\n            MultivaluedSection(multivaluedOptions: [.Reorder, .Insert, .Delete],\n                               header: \"Multivalued TextField\",\n                               footer: \".Insert multivaluedOption adds the 'Add New Tag' button row as last cell.\") {\n                                $0.tag = \"textfields\"\n                                $0.addButtonProvider = { section in\n                                    return ButtonRow(){\n                                        $0.title = \"Add New Tag\"\n                                        }.cellUpdate { cell, row in\n                                            cell.textLabel?.textAlignment = .left\n                                    }\n                                }\n                                $0.multivaluedRowToInsertAt = { index in\n                                    return NameRow() {\n                                        $0.placeholder = \"Tag Name\"\n                                    }\n                                }\n                                $0 <<< NameRow() {\n                                    $0.placeholder = \"Tag Name\"\n                                }\n            }\n\n            +++\n\n            MultivaluedSection(multivaluedOptions: [.Insert, .Delete],\n                               header: \"Multivalued ActionSheet Selector example\",\n                               footer: \".Insert multivaluedOption adds a 'Add' button row as last cell.\") {\n                                $0.tag = \"options\"\n                                $0.multivaluedRowToInsertAt = { index in\n                                    return ActionSheetRow<String>{\n                                        $0.title = \"Tap to select..\"\n                                        $0.options = [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\", \"Option 5\"]\n                                    }\n                                }\n                                $0 <<< ActionSheetRow<String> {\n                                    $0.title = \"Tap to select..\"\n                                    $0.options = [\"Option 1\", \"Option 2\", \"Option 3\", \"Option 4\", \"Option 5\"]\n                                }\n\n            }\n\n            +++\n\n            MultivaluedSection(multivaluedOptions: [.Insert, .Delete, .Reorder],\n                               header: \"Multivalued Push Selector example\") {\n                                $0.tag = \"push\"\n                                $0.multivaluedRowToInsertAt = { index in\n                                    return PushRow<String>{\n                                        $0.title = \"Tap to select ;)..at \\(index)\"\n                                        $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                    }\n                                }\n                                $0 <<< PushRow<String> {\n                                    $0.title = \"Tap to select ;)..\"\n                                    $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                }\n\n        }\n    }\n\n    @IBAction func save(_ sender: Any) {\n        print(\"\\(form.values())\")\n    }\n\n}\n\nclass MultivaluedOnlyReorderController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        let secondsPerDay = 24 * 60 * 60\n        let list = [\"Today\", \"Yesterday\", \"Before Yesterday\"]\n\n        form +++\n\n            MultivaluedSection(multivaluedOptions: .Reorder,\n                               header: \"Reordering Selectors\") {\n                                $0 <<< PushRow<String> {\n                                    $0.title = \"Tap to select ;)..\"\n                                    $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                    }\n                                    <<< PushRow<String> {\n                                        $0.title = \"Tap to select ;)..\"\n                                        $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                    }\n                                    <<< PushRow<String> {\n                                        $0.title = \"Tap to select ;)..\"\n                                        $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                    }\n                                    <<< PushRow<String> {\n                                        $0.title = \"Tap to select ;)..\"\n                                        $0.options = [\"Option 1\", \"Option 2\", \"Option 3\"]\n                                }\n\n            }\n\n            +++\n            // Multivalued Section with inline rows - section set up to support only reordering\n            MultivaluedSection(multivaluedOptions: .Reorder,\n                               header: \"Reordering Inline Rows\") { section in\n                                list.enumerated().forEach({ offset, string in\n                                    let dateInlineRow = DateInlineRow(){\n                                        $0.value = Date(timeInterval: Double(-secondsPerDay) * Double(offset), since: Date())\n                                        $0.title = string\n                                    }\n                                    section <<< dateInlineRow\n                                })\n            }\n\n            +++\n\n            MultivaluedSection(multivaluedOptions: .Reorder,\n                               header: \"Reordering Field Rows\")\n            <<< NameRow {\n                $0.value = \"Martin\"\n            }\n            <<< NameRow {\n                $0.value = \"Mathias\"\n            }\n            <<< NameRow {\n                $0.value = \"Agustin\"\n            }\n            <<< NameRow {\n                $0.value = \"Enrique\"\n        }\n\n    }\n}\n\nclass MultivaluedOnlyInsertController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        title = \"Multivalued Only Insert\"\n        form    +++\n\n            MultivaluedSection(multivaluedOptions: .Insert) { sec in\n                sec.addButtonProvider = { _ in return ButtonRow {\n                    $0.title = \"Add Tag\"\n                    }.cellUpdate { cell, row in\n                        cell.textLabel?.textAlignment = .left\n                    }\n                }\n                sec.multivaluedRowToInsertAt = { index in\n                    return TextRow {\n                        $0.placeholder = \"Tag Name\"\n                    }\n                }\n                sec.showInsertIconInAddButton = false\n            }\n\n            +++\n\n            MultivaluedSection(multivaluedOptions: .Insert, header: \"Insert With Inline Cells\") {\n                $0.multivaluedRowToInsertAt = { index in\n                    return DateInlineRow {\n                        $0.title = \"Date\"\n                        $0.value = Date()\n                    }\n                }\n        }\n    }\n}\n\nclass MultivaluedOnlyDeleteController: FormViewController {\n\n    @IBOutlet weak var editButton: UIBarButtonItem!\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        tableView.isEditing = false\n        let nameList = [\"family\", \"male\", \"female\", \"client\"]\n\n        let section = MultivaluedSection(multivaluedOptions: .Delete)\n\n        for tag in nameList {\n            section <<< TextRow {\n                $0.placeholder = \"Tag Name\"\n                $0.value = tag\n            }\n        }\n\n        let section2 =  MultivaluedSection(multivaluedOptions: .Delete, footer: \"\")\n        for _ in 1..<4 {\n            section2 <<< PickerInlineRow<String> {\n                $0.title = \"Tap to select\"\n                $0.value = \"client\"\n                $0.options = nameList\n            }\n        }\n\n        editButton.title = tableView.isEditing ? \"Done\" : \"Edit\"\n        editButton.target = self\n        editButton.action = #selector(editPressed(sender:))\n\n        form    +++\n\n            section\n\n            +++\n\n        section2\n    }\n\n    @objc func editPressed(sender: UIBarButtonItem){\n        tableView.setEditing(!tableView.isEditing, animated: true)\n        editButton.title = tableView.isEditing ? \"Done\" : \"Edit\"\n\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/NativeEventExample.swift",
    "content": "//\n//  NativeEventExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass NativeEventNavigationController: UINavigationController, RowControllerType {\n    var onDismissCallback : ((UIViewController) -> ())?\n}\n\nclass NativeEventFormViewController : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        initializeForm()\n\n        navigationItem.leftBarButtonItem?.target = self\n        navigationItem.leftBarButtonItem?.action = #selector(NativeEventFormViewController.cancelTapped(_:))\n    }\n\n    private func initializeForm() {\n\n        form +++\n\n            TextRow(\"Title\").cellSetup { cell, row in\n                cell.textField.placeholder = row.tag\n            }\n\n            <<< TextRow(\"Location\").cellSetup {\n                $1.cell.textField.placeholder = $0.row.tag\n            }\n\n            +++\n\n            SwitchRow(\"All-day\") {\n                $0.title = $0.tag\n                }.onChange { [weak self] row in\n                    let startDate: DateTimeInlineRow! = self?.form.rowBy(tag: \"Starts\")\n                    let endDate: DateTimeInlineRow! = self?.form.rowBy(tag: \"Ends\")\n\n                    if row.value ?? false {\n                        startDate.dateFormatter?.dateStyle = .medium\n                        startDate.dateFormatter?.timeStyle = .none\n                        endDate.dateFormatter?.dateStyle = .medium\n                        endDate.dateFormatter?.timeStyle = .none\n                    }\n                    else {\n                        startDate.dateFormatter?.dateStyle = .short\n                        startDate.dateFormatter?.timeStyle = .short\n                        endDate.dateFormatter?.dateStyle = .short\n                        endDate.dateFormatter?.timeStyle = .short\n                    }\n                    startDate.updateCell()\n                    endDate.updateCell()\n                    startDate.inlineRow?.updateCell()\n                    endDate.inlineRow?.updateCell()\n            }\n\n            <<< DateTimeInlineRow(\"Starts\") {\n                $0.title = $0.tag\n                $0.value = Date().addingTimeInterval(60*60*24)\n                }\n                .onChange { [weak self] row in\n                    let endRow: DateTimeInlineRow! = self?.form.rowBy(tag: \"Ends\")\n                    if row.value?.compare(endRow.value!) == .orderedDescending {\n                        endRow.value = Date(timeInterval: 60*60*24, since: row.value!)\n                        endRow.cell!.backgroundColor = .white\n                        endRow.updateCell()\n                    }\n                }\n                .onExpandInlineRow { [weak self] cell, row, inlineRow in\n                    inlineRow.cellUpdate() { cell, row in\n                        let allRow: SwitchRow! = self?.form.rowBy(tag: \"All-day\")\n                        if allRow.value ?? false {\n                            cell.datePicker.datePickerMode = .date\n                        }\n                        else {\n                            cell.datePicker.datePickerMode = .dateAndTime\n                        }\n                    }\n                    let color = cell.detailTextLabel?.textColor\n                    row.onCollapseInlineRow { cell, _, _ in\n                        cell.detailTextLabel?.textColor = color\n                    }\n                    cell.detailTextLabel?.textColor = cell.tintColor\n            }\n\n            <<< DateTimeInlineRow(\"Ends\"){\n                $0.title = $0.tag\n                $0.value = Date().addingTimeInterval(60*60*25)\n                }\n                .onChange { [weak self] row in\n                    let startRow: DateTimeInlineRow! = self?.form.rowBy(tag: \"Starts\")\n                    if row.value?.compare(startRow.value!) == .orderedAscending {\n                        row.cell!.backgroundColor = .red\n                    }\n                    else{\n                        row.cell!.backgroundColor = .white\n                    }\n                    row.updateCell()\n                }\n                .onExpandInlineRow { [weak self] cell, row, inlineRow in\n                    inlineRow.cellUpdate { cell, dateRow in\n                        let allRow: SwitchRow! = self?.form.rowBy(tag: \"All-day\")\n                        if allRow.value ?? false {\n                            cell.datePicker.datePickerMode = .date\n                        }\n                        else {\n                            cell.datePicker.datePickerMode = .dateAndTime\n                        }\n                    }\n                    let color = cell.detailTextLabel?.textColor\n                    row.onCollapseInlineRow { cell, _, _ in\n                        cell.detailTextLabel?.textColor = color\n                    }\n                    cell.detailTextLabel?.textColor = cell.tintColor\n        }\n\n        form +++\n\n            PushRow<RepeatInterval>(\"Repeat\") {\n                $0.title = $0.tag\n                $0.options = RepeatInterval.allCases\n                $0.value = .Never\n                }.onPresent({ (_, vc) in\n                    vc.enableDeselection = false\n                    vc.dismissOnSelection = false\n                })\n\n        form +++\n\n            PushRow<EventAlert>() {\n                $0.title = \"Alert\"\n                $0.options = EventAlert.allCases\n                $0.value = .Never\n                }\n                .onChange { [weak self] row in\n                    if row.value == .Never {\n                        if let second : PushRow<EventAlert> = self?.form.rowBy(tag: \"Another Alert\"), let secondIndexPath = second.indexPath {\n                            row.section?.remove(at: secondIndexPath.row)\n                        }\n                    }\n                    else{\n                        guard let _ : PushRow<EventAlert> = self?.form.rowBy(tag: \"Another Alert\") else {\n                            let second = PushRow<EventAlert>(\"Another Alert\") {\n                                $0.title = $0.tag\n                                $0.value = .Never\n                                $0.options = EventAlert.allCases\n                            }\n                            let secondIndex = row.indexPath!.row + 1\n                            row.section?.insert(second, at: secondIndex)\n                            return\n                        }\n                    }\n        }\n\n        form +++\n\n            PushRow<EventState>(\"Show As\") {\n                $0.title = \"Show As\"\n                $0.options = EventState.allCases\n        }\n\n        form +++\n\n            URLRow(\"URL\") {\n                $0.placeholder = \"URL\"\n            }\n\n            <<< TextAreaRow(\"notes\") {\n                $0.placeholder = \"Notes\"\n                $0.textAreaHeight = .dynamic(initialTextViewHeight: 50)\n        }\n\n    }\n\n    @objc func cancelTapped(_ barButtonItem: UIBarButtonItem) {\n        (navigationController as? NativeEventNavigationController)?.onDismissCallback?(self)\n    }\n\n    enum RepeatInterval : String, CaseIterable, CustomStringConvertible {\n        case Never = \"Never\"\n        case Every_Day = \"Every Day\"\n        case Every_Week = \"Every Week\"\n        case Every_2_Weeks = \"Every 2 Weeks\"\n        case Every_Month = \"Every Month\"\n        case Every_Year = \"Every Year\"\n\n        var description : String { return rawValue }\n    }\n\n    enum EventAlert : String, CaseIterable, CustomStringConvertible {\n        case Never = \"None\"\n        case At_time_of_event = \"At time of event\"\n        case Five_Minutes = \"5 minutes before\"\n        case FifTeen_Minutes = \"15 minutes before\"\n        case Half_Hour = \"30 minutes before\"\n        case One_Hour = \"1 hour before\"\n        case Two_Hour = \"2 hours before\"\n        case One_Day = \"1 day before\"\n        case Two_Days = \"2 days before\"\n\n        var description : String { return rawValue }\n    }\n\n    enum EventState : CaseIterable {\n        case busy\n        case free\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/NavigationAccessoryController.swift",
    "content": "//\n//  NavigationAccessoryController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass NavigationAccessoryController : FormViewController {\n\n    var navigationOptionsBackup : RowNavigationOptions?\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        navigationOptions = RowNavigationOptions.Enabled.union(.SkipCanNotBecomeFirstResponderRow)\n        navigationOptionsBackup = navigationOptions\n\n        form = Section(header: \"Settings\", footer: \"These settings change how the navigation accessory view behaves\")\n\n            <<< SwitchRow(\"set_none\") { [weak self] in\n                $0.title = \"Navigation accessory view\"\n                $0.value = self?.navigationOptions != .Disabled\n                }.onChange { [weak self] in\n                    if $0.value ?? false {\n                        self?.navigationOptions = self?.navigationOptionsBackup\n                        self?.form.rowBy(tag: \"set_disabled\")?.baseValue = self?.navigationOptions?.contains(.StopDisabledRow)\n                        self?.form.rowBy(tag: \"set_skip\")?.baseValue = self?.navigationOptions?.contains(.SkipCanNotBecomeFirstResponderRow)\n                        self?.form.rowBy(tag: \"set_disabled\")?.updateCell()\n                        self?.form.rowBy(tag: \"set_skip\")?.updateCell()\n                    }\n                    else {\n                        self?.navigationOptionsBackup = self?.navigationOptions\n                        self?.navigationOptions = .Disabled\n                    }\n            }\n\n            <<< CheckRow(\"set_disabled\") { [weak self] in\n                $0.title = \"Stop at disabled row\"\n                $0.value = self?.navigationOptions?.contains(.StopDisabledRow)\n                $0.hidden = \"$set_none == false\" // .Predicate(NSPredicate(format: \"$set_none == false\"))\n                }.onChange { [weak self] row in\n                    if row.value ?? false {\n                        self?.navigationOptions = self?.navigationOptions?.union(.StopDisabledRow)\n                    }\n                    else{\n                        self?.navigationOptions = self?.navigationOptions?.subtracting(.StopDisabledRow)\n                    }\n            }\n\n            <<< CheckRow(\"set_skip\") { [weak self] in\n                $0.title = \"Skip non first responder view\"\n                $0.value = self?.navigationOptions?.contains(.SkipCanNotBecomeFirstResponderRow)\n                $0.hidden = \"$set_none  == false\"\n                }.onChange { [weak self] row in\n                    if row.value ?? false {\n                        self?.navigationOptions = self?.navigationOptions?.union(.SkipCanNotBecomeFirstResponderRow)\n                    }\n                    else{\n                        self?.navigationOptions = self?.navigationOptions?.subtracting(.SkipCanNotBecomeFirstResponderRow)\n                    }\n            }\n\n\n            +++\n\n            NameRow() { $0.title = \"Your name:\" }\n\n            <<< PasswordRow() { $0.title = \"Your password:\" }\n\n            +++\n            Section()\n\n            <<< SegmentedRow<Emoji>() {\n                $0.title = \"Favourite food:\"\n                $0.options = [🐗, 🐖, 🐡, 🍐]\n            }\n\n            <<< PhoneRow() { $0.title = \"Your phone number\" }\n\n            <<< URLRow() {\n                $0.title = \"Disabled\"\n                $0.disabled = true\n            }\n\n            <<< TextRow() { $0.title = \"Your father's name\"}\n\n            <<< TextRow(){ $0.title = \"Your mother's name\"}\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/PlainTableViewExample.swift",
    "content": "//\n//  PlainTableViewExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass PlainTableViewStyleController : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form +++\n\n            Section()\n\n            <<< TextRow() {\n                $0.title = \"Name\"\n                $0.value = \"John Doe\"\n            }\n\n            <<< TextRow() {\n                $0.title = \"Username\"\n                $0.value = \"johndoe1\"\n            }\n\n            <<< EmailRow() {\n                $0.title = \"Email Address\"\n                $0.value = \"john@doe.com\"\n            }\n\n            <<< PasswordRow() {\n                $0.title = \"Password\"\n                $0.value = \"johndoe9876\"\n        }\n\n        // Remove excess separator lines on non-existent cells\n        tableView.tableFooterView = UIView()\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/RowsExample.swift",
    "content": "//\n//  RowsExample.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport CoreLocation\nimport Eureka\n\n//Mark: RowsExampleViewController\n\nclass RowsExampleViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        URLRow.defaultCellUpdate = { cell, row in cell.textField.textColor = .systemBlue }\n        LabelRow.defaultCellUpdate = { cell, row in cell.detailTextLabel?.textColor = .systemOrange  }\n        CheckRow.defaultCellSetup = { cell, row in cell.tintColor = .systemOrange }\n        DateRow.defaultRowInitializer = { row in row.minimumDate = Date() }\n\n        form +++\n\n            Section()\n\n            <<< LabelRow () {\n                $0.title = \"LabelRow\"\n                $0.value = \"tap the row\"\n                }\n                .onCellSelection { cell, row in\n                    row.title = (row.title ?? \"\") + \" 🇺🇾 \"\n                    row.reload() // or row.updateCell()\n            }\n\n            <<< DateRow() { $0.value = Date(); $0.title = \"DateRow\" }\n\n            <<< CountDownInlineRow() { $0.value = Date(); $0.title = \"CountDownInlineRow\" }\n            \n            <<< CheckRow() {\n                $0.title = \"CheckRow\"\n                $0.value = true\n            }\n\n            <<< SwitchRow() {\n                $0.title = \"SwitchRow\"\n                $0.value = true\n            }\n\n            <<< SliderRow() {\n                $0.title = \"SliderRow\"\n                $0.value = 5.0\n            }\n            .cellSetup { cell, row in\n                cell.imageView?.image = #imageLiteral(resourceName: \"selected\")\n            }\n\n            <<< StepperRow() {\n                $0.title = \"StepperRow\"\n                $0.value = 1.0\n              }.cellSetup({ (cell, row) in\n                cell.imageView?.image = #imageLiteral(resourceName: \"selectedRectangle\")\n              })\n          \n\n            +++ Section(\"SegmentedRow examples\")\n\n            <<< SegmentedRow<String>() { $0.options = [\"One\", \"Two\", \"Three\"] }\n\n            <<< SegmentedRow<Emoji>(){\n                $0.title = \"Who are you?\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻 ]\n                $0.value = 🍐\n            }\n\n            <<< SegmentedRow<String>(){\n                $0.title = \"SegmentedRow\"\n                $0.options = [\"One\", \"Two\"]\n                }.cellSetup { cell, row in\n                    cell.imageView?.image = UIImage(named: \"plus_image\")\n            }\n\n            <<< SegmentedRow<String>(){\n                $0.options = [\"One\", \"Two\", \"Three\", \"Four\"]\n                $0.value = \"Three\"\n                }.cellSetup { cell, row in\n                    cell.imageView?.image = UIImage(named: \"plus_image\")\n            }\n\n            <<< SegmentedRow<UIImage>(){\n                let names = [\"selected\", \"plus_image\", \"unselected\"]\n                $0.options = names.map { UIImage(named: $0)! }\n                $0.value = $0.options?.last\n            }\n\n            +++ Section(\"Selectors Rows Examples\")\n\n            <<< ActionSheetRow<String>() {\n                $0.title = \"ActionSheetRow\"\n                $0.selectorTitle = \"Your favourite player?\"\n                $0.options = [\"Diego Forlán\", \"Edinson Cavani\", \"Diego Lugano\", \"Luis Suarez\"]\n                $0.value = \"Luis Suarez\"\n                }\n                .onPresent { from, to in\n                    to.popoverPresentationController?.permittedArrowDirections = .up\n            }\n\n            <<< AlertRow<Emoji>() {\n                $0.title = \"AlertRow\"\n                $0.cancelTitle = \"Dismiss\"\n                $0.selectorTitle = \"Who is there?\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = 👦🏼\n                }.onChange { row in\n                    print(row.value ?? \"No Value\")\n                }\n                .onPresent{ _, to in\n                    to.view.tintColor = .purple\n            }\n\n            <<< PushRow<Emoji>() {\n                $0.title = \"PushRow\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = 👦🏼\n                $0.selectorTitle = \"Choose an Emoji!\"\n                }.onPresent { from, to in\n                    to.dismissOnSelection = false\n                    to.dismissOnChange = false\n            }\n\n            <<< PushRow<Emoji>() {\n                $0.title = \"SectionedPushRow\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = 👦🏼\n                $0.selectorTitle = \"Choose an Emoji!\"\n                }.onPresent { from, to in\n                    to.dismissOnSelection = false\n                    to.dismissOnChange = false\n                    to.sectionKeyForValue = { option in\n                        switch option {\n                        case 💁🏻, 👦🏼: return \"People\"\n                        case 🐗, 🐼, 🐻: return \"Animals\"\n                        case 🍐: return \"Food\"\n                        default: return \"\"\n                        }\n                    }\n            }\n            <<< PushRow<Emoji>() {\n                $0.title = \"LazySectionedPushRow\"\n                $0.value = 👦🏼\n                $0.selectorTitle = \"Choose a lazy Emoji!\"\n                $0.optionsProvider = .lazy({ (form, completion) in\n                    let activityView = UIActivityIndicatorView(style: .gray)\n                    form.tableView.backgroundView = activityView\n                    activityView.startAnimating()\n                    DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {\n                        form.tableView.backgroundView = nil\n                        completion([💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻])\n                    })\n                })\n                }\n                .onPresent { from, to in\n                    to.sectionKeyForValue = { option -> String in\n                        switch option {\n                        case 💁🏻, 👦🏼: return \"People\"\n                        case 🐗, 🐼, 🐻: return \"Animals\"\n                        case 🍐: return \"Food\"\n                        default: return \"\"\n                        }\n                    }\n        }\n\n            <<< PushRow<Emoji>() {\n                $0.title = \"Custom Cell Push Row\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = 👦🏼\n                $0.selectorTitle = \"Choose an Emoji!\"\n                }\n                .onPresent { from, to in\n                    to.selectableRowSetup = { row in\n                        row.cellProvider = CellProvider<ListCheckCell<Emoji>>(nibName: \"EmojiCell\", bundle: Bundle.main)\n                    }\n                    to.selectableRowCellUpdate = { cell, row in\n                        var detailText: String?\n                        switch row.selectableValue {\n                        case 💁🏻, 👦🏼: detailText = \"Person\"\n                        case 🐗, 🐼, 🐻: detailText = \"Animal\"\n                        case 🍐: detailText = \"Food\"\n                        default: detailText = \"\"\n                        }\n                        cell.detailTextLabel?.text = detailText\n                    }\n        }\n\n\n        if UIDevice.current.userInterfaceIdiom == .pad {\n            let section = form.last!\n\n            section <<< PopoverSelectorRow<Emoji>() {\n                $0.title = \"PopoverSelectorRow\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = 💁🏻\n                $0.selectorTitle = \"Choose an Emoji!\"\n            }\n        }\n\n        let section = form.last!\n\n        section\n            <<< LocationRow(){\n                $0.title = \"LocationRow\"\n                $0.value = CLLocation(latitude: -34.9124, longitude: -56.1594)\n            }\n\n            <<< ImageRow(){\n                $0.title = \"ImageRow\"\n            }\n\n            <<< MultipleSelectorRow<Emoji>() {\n                $0.title = \"MultipleSelectorRow\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = [👦🏼, 🍐, 🐗]\n                }\n                .onPresent { from, to in\n                    to.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: from, action: #selector(RowsExampleViewController.multipleSelectorDone(_:)))\n            }\n\n            <<< MultipleSelectorRow<Emoji>() {\n                $0.title = \"SectionedMultipleSelectorRow\"\n                $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n                $0.value = [👦🏼, 🍐, 🐗]\n                }\n                .onPresent { from, to in\n                    to.sectionKeyForValue = { option in\n                        switch option {\n                        case 💁🏻, 👦🏼: return \"People\"\n                        case 🐗, 🐼, 🐻: return \"Animals\"\n                        case 🍐: return \"Food\"\n                        default: return \"\"\n                        }\n                    }\n                    to.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: from, action: #selector(RowsExampleViewController.multipleSelectorDone(_:)))\n            }\n            <<< MultipleSelectorRow<Emoji>() {\n                $0.title = \"LazyMultipleSelectorRow\"\n                $0.value = [👦🏼, 🍐, 🐗]\n                $0.optionsProvider = .lazy({ (form, completion) in\n                    let activityView = UIActivityIndicatorView(style: .gray)\n                    form.tableView.backgroundView = activityView\n                    activityView.startAnimating()\n                    DispatchQueue.main.asyncAfter(deadline: .now() + 3, execute: {\n                        form.tableView.backgroundView = nil\n                        completion([💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻])\n                    })\n                })\n                }.onPresent { from, to in\n                    to.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: from, action: #selector(RowsExampleViewController.multipleSelectorDone(_:)))\n        }\n\n        form +++ Section(\"Generic picker\")\n\n            <<< PickerRow<String>(\"Picker Row\") { (row : PickerRow<String>) -> Void in\n\n                row.options = []\n                for i in 1...10{\n                    row.options.append(\"option \\(i)\")\n                }\n            }\n\n            <<< PickerInputRow<String>(\"Picker Input Row\"){\n                $0.title = \"Options\"\n                $0.options = []\n                for i in 1...10{\n                    $0.options.append(\"option \\(i)\")\n                }\n                $0.value = $0.options.first\n            }\n            \n            <<< DoublePickerInlineRow<String, Int>() {\n                $0.title = \"2 Component picker\"\n                $0.firstOptions = { return [\"a\", \"b\", \"c\"]}\n                $0.secondOptions = { _ in return [1, 2, 3]}\n            }\n            <<< TriplePickerInputRow<String, String, Int>() {\n                $0.firstOptions = { return [\"a\", \"b\", \"c\"]}\n                $0.secondOptions = { return [$0, $0 + $0, $0 + \"-\" + $0, \"asd\"]}\n                $0.thirdOptions = { _,_ in return [1, 2, 3]}\n                $0.title = \"3 Component picker\"\n            }\n\n            +++ Section(\"FieldRow examples\")\n\n            <<< TextRow() {\n                $0.title = \"TextRow\"\n                $0.placeholder = \"Placeholder\"\n            }\n\n            <<< DecimalRow() {\n                $0.title = \"DecimalRow\"\n                $0.value = 5\n                $0.formatter = DecimalFormatter()\n                $0.useFormatterDuringInput = true\n                //$0.useFormatterOnDidBeginEditing = true\n                }.cellSetup { cell, _  in\n                    cell.textField.keyboardType = .numberPad\n            }\n\n            <<< URLRow() {\n                $0.title = \"URLRow\"\n                $0.value = URL(string: \"http://xmartlabs.com\")\n            }\n\n            <<< PhoneRow() {\n                $0.title = \"PhoneRow (disabled)\"\n                $0.value = \"+598 9898983510\"\n                $0.disabled = true\n            }\n\n            <<< NameRow() {\n                $0.title =  \"NameRow\"\n            }\n\n            <<< PasswordRow() {\n                $0.title = \"PasswordRow\"\n                $0.value = \"password\"\n            }\n\n            <<< IntRow() {\n                $0.title = \"IntRow\"\n                $0.value = 2015\n            }\n\n            <<< EmailRow() {\n                $0.title = \"EmailRow\"\n                $0.value = \"a@b.com\"\n            }\n\n            <<< TwitterRow() {\n                $0.title = \"TwitterRow\"\n                $0.value = \"@xmartlabs\"\n            }\n\n            <<< AccountRow() {\n                $0.title = \"AccountRow\"\n                $0.placeholder = \"Placeholder\"\n            }\n\n            <<< ZipCodeRow() {\n                $0.title = \"ZipCodeRow\"\n                $0.placeholder = \"90210\"\n        }\n\n    }\n\n    @objc func multipleSelectorDone(_ item:UIBarButtonItem) {\n        _ = navigationController?.popViewController(animated: true)\n    }\n\n}\n"
  },
  {
    "path": "Example/Example/Controllers/SwipeActionsController.swift",
    "content": "//\n//  SwipeActionsController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass SwipeActionsController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        form +++ Section(footer: \"Eureka sets table.isEditing = true only if the form contains a MultivaluedSection. SwipeActions only work when isEditing = false, therefore you have to set that in ViewWillAppear. Both can't be used on the same form.\")\n            <<< LabelRow(\"Actions Right: iOS >= 7\") {\n                $0.title = $0.tag\n\n                let moreAction = SwipeAction(style: .normal, title: \"More\", handler: { (action, row, completionHandler) in\n                    print(\"More\")\n                    completionHandler?(true)\n                })\n\n                let deleteAction = SwipeAction(style: .destructive, title: \"Delete\") { (action, row, completionHandler) in\n                    print(\"Delete\")\n                    completionHandler?(true)\n                }\n\n                $0.trailingSwipe.actions = [deleteAction,moreAction]\n\n            }\n\n            <<< LabelRow(\"Actions Left & Right: iOS >= 11\") {\n                $0.title = $0.tag\n\n                let moreAction = SwipeAction(style: .normal, title: \"More\") { (action, row, completionHandler) in\n                    print(\"More\")\n                    completionHandler?(true)\n                }\n\n                let deleteAction = SwipeAction(style: .destructive, title: \"Delete\", handler: { (action, row, completionHandler) in\n                    print(\"Delete\")\n                    completionHandler?(true)\n                })\n\n                $0.trailingSwipe.actions = [deleteAction,moreAction]\n                $0.trailingSwipe.performsFirstActionWithFullSwipe = true\n\n                if #available(iOS 11,*) {\n                    let infoAction = SwipeAction(style: .normal, title: \"Info\", handler: { (action, row, completionHandler) in\n                        print(\"Info\")\n                        completionHandler?(true)\n                    })\n                    infoAction.actionBackgroundColor = .blue\n\n                    $0.leadingSwipe.actions = [infoAction]\n                    $0.leadingSwipe.performsFirstActionWithFullSwipe = true\n                }\n        }\n    }\n}\n"
  },
  {
    "path": "Example/Example/Controllers/ValidationsController.swift",
    "content": "//\n//  ValidationsController.swift\n//  Example\n//\n//  Created by Mathias Claassen on 3/15/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Eureka\n\nclass ValidationsController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        LabelRow.defaultCellUpdate = { cell, row in\n            cell.contentView.backgroundColor = .red\n            cell.textLabel?.textColor = .white\n            cell.textLabel?.font = UIFont.boldSystemFont(ofSize: 13)\n            cell.textLabel?.textAlignment = .right\n\n        }\n\n        TextRow.defaultCellUpdate = { cell, row in\n            if !row.isValid {\n                cell.titleLabel?.textColor = .red\n            }\n        }\n\n        form\n            +++ Section(header: \"Required Rule\", footer: \"Options: Validates on change\")\n\n            <<< TextRow() {\n                $0.title = \"Required Rule\"\n                $0.add(rule: RuleRequired())\n                $0.validationOptions = .validatesOnChange\n            }\n\n            +++ Section(header: \"Email Rule, Required Rule\", footer: \"Options: Validates on change after blurred\")\n\n            <<< TextRow() {\n                $0.title = \"Email Rule\"\n                $0.add(rule: RuleRequired())\n                var ruleSet = RuleSet<String>()\n                ruleSet.add(rule: RuleRequired())\n                ruleSet.add(rule: RuleEmail())\n                $0.add(ruleSet: ruleSet)\n                $0.validationOptions = .validatesOnChangeAfterBlurred\n            }\n\n            +++ Section(header: \"URL Rule\", footer: \"Options: Validates on change\")\n\n            <<< URLRow() {\n                $0.title = \"URL Rule\"\n                $0.add(rule: RuleURL())\n                $0.validationOptions = .validatesOnChange\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n            }\n\n            +++ Section(header: \"MinLength 8 Rule, MaxLength 13 Rule\", footer: \"Options: Validates on blurred\")\n            <<< PasswordRow() {\n                $0.title = \"Password\"\n                $0.add(rule: RuleMinLength(minLength: 8))\n                $0.add(rule: RuleMaxLength(maxLength: 13))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n            }\n\n            +++ Section(header: \"Should be GreaterThan 2 and SmallerThan 999\", footer: \"Options: Validates on blurred\")\n\n            <<< IntRow() {\n                $0.title = \"Range Rule\"\n                $0.add(rule: RuleGreaterThan(min: 2))\n                $0.add(rule: RuleSmallerThan(max: 999))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n            }\n\n            +++ Section(header: \"Match field values\", footer: \"Options: Validates on blurred\")\n\n            <<< PasswordRow(\"password\") {\n                $0.title = \"Password\"\n            }\n            <<< PasswordRow() {\n                $0.title = \"Confirm Password\"\n                $0.add(rule: RuleEqualsToRow(form: form, tag: \"password\"))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n            }\n\n            +++ Section(header: \"More sophisticated validations UX using callbacks\", footer: \"\")\n\n            <<< TextRow() {\n                $0.title = \"Required Rule\"\n                $0.add(rule: RuleRequired())\n                $0.validationOptions = .validatesOnChange\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            <<< EmailRow() {\n                $0.title = \"Email Rule\"\n                $0.add(rule: RuleRequired())\n                $0.add(rule: RuleEmail())\n                $0.validationOptions = .validatesOnChangeAfterBlurred\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            <<< URLRow() {\n                $0.title = \"URL Rule\"\n                $0.add(rule: RuleURL())\n                $0.validationOptions = .validatesOnChange\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            <<< PasswordRow(\"password2\") {\n                $0.title = \"Password\"\n                $0.add(rule: RuleMinLength(minLength: 8))\n                $0.add(rule: RuleMaxLength(maxLength: 13))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            <<< PasswordRow() {\n                $0.title = \"Confirm Password\"\n                $0.add(rule: RuleEqualsToRow(form: form, tag: \"password2\"))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            <<< IntRow() {\n                $0.title = \"Range Rule\"\n                $0.add(rule: RuleGreaterThan(min: 2))\n                $0.add(rule: RuleSmallerThan(max: 999))\n                }\n                .cellUpdate { cell, row in\n                    if !row.isValid {\n                        cell.titleLabel?.textColor = .red\n                    }\n                }\n                .onRowValidationChanged { cell, row in\n                    let rowIndex = row.indexPath!.row\n                    while row.section!.count > rowIndex + 1 && row.section?[rowIndex  + 1] is LabelRow {\n                        row.section?.remove(at: rowIndex + 1)\n                    }\n                    if !row.isValid {\n                        for (index, validationMsg) in row.validationErrors.map({ $0.msg }).enumerated() {\n                            let labelRow = LabelRow() {\n                                $0.title = validationMsg\n                                $0.cell.height = { 30 }\n                            }\n                            let indexPath = row.indexPath!.row + index + 1\n                            row.section?.insert(labelRow, at: indexPath)\n                        }\n                    }\n            }\n\n            +++ Section()\n                <<< ButtonRow() {\n                    $0.title = \"Tap to force form validation\"\n                }\n                .onCellSelection { cell, row in\n                    row.section?.form?.validate()\n                }\n    }\n}\n"
  },
  {
    "path": "Example/Example/CustomCells.swift",
    "content": "//  CustomCells.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\nimport MapKit\nimport Eureka\n\n//MARK: WeeklyDayCell\n\npublic enum WeekDay {\n    case monday, tuesday, wednesday, thursday, friday, saturday, sunday\n}\n\npublic class WeekDayCell : Cell<Set<WeekDay>>, CellType {\n\n    @IBOutlet var sundayButton: UIButton!\n    @IBOutlet var mondayButton: UIButton!\n    @IBOutlet var tuesdayButton: UIButton!\n    @IBOutlet var wednesdayButton: UIButton!\n    @IBOutlet var thursdayButton: UIButton!\n    @IBOutlet var fridayButton: UIButton!\n    @IBOutlet var saturdayButton: UIButton!\n\n    open override func setup() {\n        height = { 60 }\n        row.title = nil\n        super.setup()\n        selectionStyle = .none\n        for subview in contentView.subviews {\n            if let button = subview as? UIButton {\n                button.setImage(UIImage(named: \"checkedDay\"), for: .selected)\n                button.setImage(UIImage(named: \"uncheckedDay\"), for: .normal)\n                button.adjustsImageWhenHighlighted = false\n                imageTopTitleBottom(button)\n            }\n        }\n    }\n\n    open override func update() {\n        row.title = nil\n        super.update()\n        let value = row.value\n        mondayButton.isSelected = value?.contains(.monday) ?? false\n        tuesdayButton.isSelected = value?.contains(.tuesday) ?? false\n        wednesdayButton.isSelected = value?.contains(.wednesday) ?? false\n        thursdayButton.isSelected = value?.contains(.thursday) ?? false\n        fridayButton.isSelected = value?.contains(.friday) ?? false\n        saturdayButton.isSelected = value?.contains(.saturday) ?? false\n        sundayButton.isSelected = value?.contains(.sunday) ?? false\n\n        mondayButton.alpha = row.isDisabled ? 0.6 : 1.0\n        tuesdayButton.alpha = mondayButton.alpha\n        wednesdayButton.alpha = mondayButton.alpha\n        thursdayButton.alpha = mondayButton.alpha\n        fridayButton.alpha = mondayButton.alpha\n        saturdayButton.alpha = mondayButton.alpha\n        sundayButton.alpha = mondayButton.alpha\n    }\n\n    @IBAction func dayTapped(_ sender: UIButton) {\n        dayTapped(sender, day: getDayFromButton(sender))\n    }\n\n    private func getDayFromButton(_ button: UIButton) -> WeekDay{\n        switch button{\n        case sundayButton:\n            return .sunday\n        case mondayButton:\n            return .monday\n        case tuesdayButton:\n            return .tuesday\n        case wednesdayButton:\n            return .wednesday\n        case thursdayButton:\n            return .thursday\n        case fridayButton:\n            return .friday\n        default:\n            return .saturday\n        }\n    }\n\n    private func dayTapped(_ button: UIButton, day: WeekDay){\n        button.isSelected = !button.isSelected\n        if button.isSelected{\n            row.value?.insert(day)\n        }\n        else{\n            _ = row.value?.remove(day)\n        }\n    }\n\n    private func imageTopTitleBottom(_ button : UIButton){\n\n        guard let imageSize = button.imageView?.image?.size else { return }\n        let spacing : CGFloat = 3.0\n        button.titleEdgeInsets = UIEdgeInsets(top: 0.0, left: -imageSize.width, bottom: -(imageSize.height + spacing), right: 0.0)\n        guard let titleLabel = button.titleLabel, let title = titleLabel.text else { return }\n        let titleSize = title.size(withAttributes: [.font: titleLabel.font!])\n        button.imageEdgeInsets = UIEdgeInsets(top: -(titleSize.height + spacing), left: 0, bottom: 0, right: -titleSize.width)\n    }\n}\n\n//MARK: WeekDayRow\n\npublic final class WeekDayRow: Row<WeekDayCell>, RowType {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n        cellProvider = CellProvider<WeekDayCell>(nibName: \"WeekDaysCell\")\n    }\n}\n\n\n//MARK: FloatLabelCell\n\npublic class _FloatLabelCell<T>: Cell<T>, UITextFieldDelegate, TextFieldCell where T: Equatable, T: InputTypeInitiable {\n\n    public var textField: UITextField! { return floatLabelTextField }\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    lazy public var floatLabelTextField: FloatLabelTextField = { [unowned self] in\n        let floatTextField = FloatLabelTextField()\n        floatTextField.translatesAutoresizingMaskIntoConstraints = false\n        floatTextField.font = .preferredFont(forTextStyle: .body)\n        floatTextField.titleFont = .boldSystemFont(ofSize: 11.0)\n        floatTextField.clearButtonMode = .whileEditing\n        return floatTextField\n        }()\n\n\n    open override func setup() {\n        super.setup()\n        height = { 55 }\n        selectionStyle = .none\n        contentView.addSubview(floatLabelTextField)\n        floatLabelTextField.delegate = self\n        floatLabelTextField.addTarget(self, action: #selector(_FloatLabelCell.textFieldDidChange(_:)), for: .editingChanged)\n        contentView.addConstraints(layoutConstraints())\n    }\n\n    open override func update() {\n        super.update()\n        textLabel?.text = nil\n        detailTextLabel?.text = nil\n        floatLabelTextField.attributedPlaceholder = NSAttributedString(string: row.title ?? \"\", attributes: [.foregroundColor: UIColor.lightGray])\n        floatLabelTextField.text =  row.displayValueFor?(row.value)\n        floatLabelTextField.isEnabled = !row.isDisabled\n        floatLabelTextField.titleTextColour = .lightGray\n        floatLabelTextField.alpha = row.isDisabled ? 0.6 : 1\n    }\n\n    open override func cellCanBecomeFirstResponder() -> Bool {\n        return !row.isDisabled && floatLabelTextField.canBecomeFirstResponder\n    }\n\n    open override func cellBecomeFirstResponder(withDirection direction: Direction) -> Bool {\n        return floatLabelTextField.becomeFirstResponder()\n    }\n\n    open override func cellResignFirstResponder() -> Bool {\n        return floatLabelTextField.resignFirstResponder()\n    }\n\n    private func layoutConstraints() -> [NSLayoutConstraint] {\n        let views = [\"floatLabeledTextField\": floatLabelTextField]\n        let metrics = [\"vMargin\":8.0]\n        return NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[floatLabeledTextField]-|\", options: .alignAllLastBaseline, metrics: metrics, views: views) + NSLayoutConstraint.constraints(withVisualFormat: \"V:|-(vMargin)-[floatLabeledTextField]-(vMargin)-|\", options: .alignAllLastBaseline, metrics: metrics, views: views)\n    }\n\n    @objc public func textFieldDidChange(_ textField : UITextField){\n        guard let textValue = textField.text else {\n            row.value = nil\n            return\n        }\n        if let fieldRow = row as? FormatterConformance, let formatter = fieldRow.formatter {\n            if fieldRow.useFormatterDuringInput {\n                let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))\n                let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n                if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                    row.value = value.pointee as? T\n                    if var selStartPos = textField.selectedTextRange?.start {\n                        let oldVal = textField.text\n                        textField.text = row.displayValueFor?(row.value)\n                        if let f = formatter as? FormatterProtocol {\n                            selStartPos = f.getNewPosition(forPosition: selStartPos, inTextInput: textField, oldValue: oldVal, newValue: textField.text)\n                        }\n                        textField.selectedTextRange = textField.textRange(from: selStartPos, to: selStartPos)\n                    }\n                    return\n                }\n            }\n            else {\n                let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))\n                let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n                if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                    row.value = value.pointee as? T\n                }\n                return\n            }\n        }\n        guard !textValue.isEmpty else {\n            row.value = nil\n            return\n        }\n        guard let newValue = T.init(string: textValue) else {\n            return\n        }\n        row.value = newValue\n    }\n\n\n    //Mark: Helpers\n\n    private func displayValue(useFormatter: Bool) -> String? {\n        guard let v = row.value else { return nil }\n        if let formatter = (row as? FormatterConformance)?.formatter, useFormatter {\n            return textField?.isFirstResponder == true ? formatter.editingString(for: v) : formatter.string(for: v)\n        }\n        return String(describing: v)\n    }\n\n    //MARK: TextFieldDelegate\n\n    public func textFieldDidBeginEditing(_ textField: UITextField) {\n        formViewController()?.beginEditing(of: self)\n        if let fieldRowConformance = row as? FormatterConformance, let _ = fieldRowConformance.formatter, fieldRowConformance.useFormatterOnDidBeginEditing ?? fieldRowConformance.useFormatterDuringInput {\n            textField.text = displayValue(useFormatter: true)\n        } else {\n            textField.text = displayValue(useFormatter: false)\n        }\n    }\n\n    public func textFieldDidEndEditing(_ textField: UITextField) {\n        formViewController()?.endEditing(of: self)\n        formViewController()?.textInputDidEndEditing(textField, cell: self)\n        textFieldDidChange(textField)\n        textField.text = displayValue(useFormatter: (row as? FormatterConformance)?.formatter != nil)\n    }\n}\n\npublic class TextFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .default\n        textField?.autocapitalizationType = .sentences\n        textField?.keyboardType = .default\n    }\n}\n\n\npublic class IntFloatLabelCell : _FloatLabelCell<Int>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .default\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .numberPad\n    }\n}\n\npublic class PhoneFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.keyboardType = .phonePad\n    }\n}\n\npublic class NameFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .words\n        textField.keyboardType = .asciiCapable\n    }\n}\n\npublic class EmailFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .no\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .emailAddress\n    }\n}\n\npublic class PasswordFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .no\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .asciiCapable\n        textField?.isSecureTextEntry = true\n    }\n}\n\npublic class DecimalFloatLabelCell : _FloatLabelCell<Float>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.keyboardType = .decimalPad\n    }\n}\n\npublic class URLFloatLabelCell : _FloatLabelCell<URL>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .no\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .URL\n    }\n}\n\npublic class TwitterFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .no\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .twitter\n    }\n}\n\npublic class AccountFloatLabelCell : _FloatLabelCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    public override func setup() {\n        super.setup()\n        textField?.autocorrectionType = .no\n        textField?.autocapitalizationType = .none\n        textField?.keyboardType = .asciiCapable\n    }\n}\n\n\n\n//MARK: FloatLabelRow\n\nopen class FloatFieldRow<Cell: CellType>: FormatteableRow<Cell> where Cell: BaseCell, Cell: TextFieldCell {\n\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\npublic final class TextFloatLabelRow: FloatFieldRow<TextFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class IntFloatLabelRow: FloatFieldRow<IntFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class DecimalFloatLabelRow: FloatFieldRow<DecimalFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class URLFloatLabelRow: FloatFieldRow<URLFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class TwitterFloatLabelRow: FloatFieldRow<TwitterFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class AccountFloatLabelRow: FloatFieldRow<AccountFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class PasswordFloatLabelRow: FloatFieldRow<PasswordFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class NameFloatLabelRow: FloatFieldRow<NameFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class EmailFloatLabelRow: FloatFieldRow<EmailFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\npublic final class PhoneFloatLabelRow: FloatFieldRow<PhoneFloatLabelCell>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n\n//MARK: LocationRow\n\npublic final class LocationRow: OptionsRow<PushSelectorCell<CLLocation>>, PresenterRowType, RowType {\n    \n    public typealias PresenterRow = MapViewController\n    \n    /// Defines how the view controller will be presented, pushed, etc.\n    public var presentationMode: PresentationMode<PresenterRow>?\n    \n    /// Will be called before the presentation occurs.\n    public var onPresentCallback: ((FormViewController, PresenterRow) -> Void)?\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        presentationMode = .show(controllerProvider: ControllerProvider.callback { return MapViewController(){ _ in } }, onDismiss: { vc in _ = vc.navigationController?.popViewController(animated: true) })\n\n        displayValueFor = {\n            guard let location = $0 else { return \"\" }\n            let fmt = NumberFormatter()\n            fmt.maximumFractionDigits = 4\n            fmt.minimumFractionDigits = 4\n            let latitude = fmt.string(from: NSNumber(value: location.coordinate.latitude))!\n            let longitude = fmt.string(from: NSNumber(value: location.coordinate.longitude))!\n            return  \"\\(latitude), \\(longitude)\"\n        }\n    }\n    \n    /**\n     Extends `didSelect` method\n     */\n    public override func customDidSelect() {\n        super.customDidSelect()\n        guard let presentationMode = presentationMode, !isDisabled else { return }\n        if let controller = presentationMode.makeController() {\n            controller.row = self\n            controller.title = selectorTitle ?? controller.title\n            onPresentCallback?(cell.formViewController()!, controller)\n            presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n        } else {\n            presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n        }\n    }\n    \n    /**\n     Prepares the pushed row setting its title and completion callback.\n     */\n    public override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as? PresenterRow else { return }\n        rowVC.title = selectorTitle ?? rowVC.title\n        rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback\n        onPresentCallback?(cell.formViewController()!, rowVC)\n        rowVC.row = self\n    }\n}\n\npublic class MapViewController : UIViewController, TypedRowControllerType, MKMapViewDelegate {\n\n    public var row: RowOf<CLLocation>!\n    public var onDismissCallback: ((UIViewController) -> ())?\n\n    lazy var mapView : MKMapView = { [unowned self] in\n        let v = MKMapView(frame: self.view.bounds)\n        v.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n        return v\n        }()\n\n    lazy var pinView: UIImageView = { [unowned self] in\n        let v = UIImageView(frame: CGRect(x: 0, y: 0, width: 50, height: 50))\n        v.image = UIImage(named: \"map_pin\", in: Bundle(for: MapViewController.self), compatibleWith: nil)\n        v.image = v.image?.withRenderingMode(.alwaysTemplate)\n        v.tintColor = self.view.tintColor\n        v.backgroundColor = .clear\n        v.clipsToBounds = true\n        v.contentMode = .scaleAspectFit\n        v.isUserInteractionEnabled = false\n        return v\n        }()\n\n    let width: CGFloat = 10.0\n    let height: CGFloat = 5.0\n\n    lazy var ellipse: UIBezierPath = { [unowned self] in\n        let ellipse = UIBezierPath(ovalIn: CGRect(x: 0, y: 0, width: self.width, height: self.height))\n        return ellipse\n        }()\n\n\n    lazy var ellipsisLayer: CAShapeLayer = { [unowned self] in\n        let layer = CAShapeLayer()\n        layer.bounds = CGRect(x: 0, y: 0, width: self.width, height: self.height)\n        layer.path = self.ellipse.cgPath\n        layer.fillColor = UIColor.gray.cgColor\n        layer.fillRule = .nonZero\n        layer.lineCap = .butt\n        layer.lineDashPattern = nil\n        layer.lineDashPhase = 0.0\n        layer.lineJoin = .miter\n        layer.lineWidth = 1.0\n        layer.miterLimit = 10.0\n        layer.strokeColor = UIColor.gray.cgColor\n        return layer\n        }()\n\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n        super.init(nibName: nil, bundle: nil)\n    }\n\n    convenience public init(_ callback: ((UIViewController) -> ())?){\n        self.init(nibName: nil, bundle: nil)\n        onDismissCallback = callback\n    }\n\n    public override func viewDidLoad() {\n        super.viewDidLoad()\n        view.addSubview(mapView)\n\n        mapView.delegate = self\n        mapView.addSubview(pinView)\n        mapView.layer.insertSublayer(ellipsisLayer, below: pinView.layer)\n\n        let button = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(MapViewController.tappedDone(_:)))\n        button.title = \"Done\"\n        navigationItem.rightBarButtonItem = button\n\n        if let value = row.value {\n            let region = MKCoordinateRegion(center: value.coordinate, latitudinalMeters: 400, longitudinalMeters: 400)\n            mapView.setRegion(region, animated: true)\n        }\n        else{\n            mapView.showsUserLocation = true\n        }\n        updateTitle()\n\n    }\n\n    public override func viewWillAppear(_ animated: Bool) {\n        super.viewWillAppear(animated)\n\n        let center = mapView.convert(mapView.centerCoordinate, toPointTo: pinView)\n        pinView.center = CGPoint(x: center.x, y: center.y - (pinView.bounds.height/2))\n        ellipsisLayer.position = center\n    }\n\n\n    @objc func tappedDone(_ sender: UIBarButtonItem){\n        let target = mapView.convert(ellipsisLayer.position, toCoordinateFrom: mapView)\n        row.value = CLLocation(latitude: target.latitude, longitude: target.longitude)\n        onDismissCallback?(self)\n    }\n\n    func updateTitle(){\n        let fmt = NumberFormatter()\n        fmt.maximumFractionDigits = 4\n        fmt.minimumFractionDigits = 4\n        let latitude = fmt.string(from: NSNumber(value: mapView.centerCoordinate.latitude))!\n        let longitude = fmt.string(from: NSNumber(value: mapView.centerCoordinate.longitude))!\n        title = \"\\(latitude), \\(longitude)\"\n    }\n\n    public func mapView(_ mapView: MKMapView, regionWillChangeAnimated animated: Bool) {\n        ellipsisLayer.transform = CATransform3DMakeScale(0.5, 0.5, 1)\n        UIView.animate(withDuration: 0.2, animations: { [weak self] in\n            self?.pinView.center = CGPoint(x: self!.pinView.center.x, y: self!.pinView.center.y - 10)\n            })\n    }\n\n    public func mapView(_ mapView: MKMapView, regionDidChangeAnimated animated: Bool) {\n        ellipsisLayer.transform = CATransform3DIdentity\n        UIView.animate(withDuration: 0.2, animations: { [weak self] in\n            self?.pinView.center = CGPoint(x: self!.pinView.center.x, y: self!.pinView.center.y + 10)\n            })\n        updateTitle()\n    }\n}\n\npublic final class ImageCheckRow<T: Equatable>: Row<ImageCheckCell<T>>, SelectableRowType, RowType {\n    public var selectableValue: T?\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n    }\n}\n\npublic class ImageCheckCell<T: Equatable> : Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    /// Image for selected state\n    lazy public var trueImage: UIImage = {\n        return UIImage(named: \"selected\")!\n    }()\n\n    /// Image for unselected state\n    lazy public var falseImage: UIImage = {\n        return UIImage(named: \"unselected\")!\n    }()\n\n    public override func update() {\n        super.update()\n        checkImageView?.image = row.value != nil ? trueImage : falseImage\n        checkImageView?.sizeToFit()\n    }\n    \n    /// Image view to render images. If `accessoryType` is set to `checkmark`\n    /// will create a new `UIImageView` and set it as `accessoryView`.\n    /// Otherwise returns `self.imageView`.\n    open var checkImageView: UIImageView? {\n        guard accessoryType == .checkmark else {\n            return self.imageView\n        }\n        \n        guard let accessoryView = accessoryView else {\n            let imageView = UIImageView()\n            self.accessoryView = imageView\n            return imageView\n        }\n        \n        return accessoryView as? UIImageView\n    }\n\n    public override func setup() {\n        super.setup()\n        accessoryType = .none\n    }\n\n    public override func didSelect() {\n        row.reload()\n        row.select()\n        row.deselect()\n    }\n\n}\n\nclass EmojiCell: ListCheckCell<Emoji> {}\n"
  },
  {
    "path": "Example/Example/CustomDesign/DatePickerCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"11762\" systemVersion=\"16C67\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"11757\"/>\n        <capability name=\"Constraints to layout margins\" minToolsVersion=\"6.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" selectionStyle=\"none\" indentationWidth=\"10\" rowHeight=\"345\" id=\"TGd-ph-tUe\" customClass=\"DatePickerCell\" customModule=\"Eureka\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"345\"/>\n            <autoresizingMask key=\"autoresizingMask\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"TGd-ph-tUe\" id=\"SE6-XM-XUK\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"344.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <datePicker contentMode=\"scaleToFill\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" datePickerMode=\"dateAndTime\" minuteInterval=\"1\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"QTF-rn-j0f\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"36\" width=\"375\" height=\"216\"/>\n                        <date key=\"date\" timeIntervalSinceReferenceDate=\"508107183.67711699\">\n                            <!--2017-02-06 20:53:03 +0000-->\n                        </date>\n                    </datePicker>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Just another Label\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"a4v-A6-gjw\">\n                        <rect key=\"frame\" x=\"116\" y=\"287\" width=\"142\" height=\"21\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                </subviews>\n                <constraints>\n                    <constraint firstAttribute=\"bottomMargin\" secondItem=\"QTF-rn-j0f\" secondAttribute=\"bottom\" constant=\"84.5\" id=\"70g-uP-Pqb\"/>\n                    <constraint firstItem=\"a4v-A6-gjw\" firstAttribute=\"top\" secondItem=\"QTF-rn-j0f\" secondAttribute=\"bottom\" constant=\"35\" id=\"CEg-DX-NzK\"/>\n                    <constraint firstItem=\"QTF-rn-j0f\" firstAttribute=\"top\" secondItem=\"SE6-XM-XUK\" secondAttribute=\"top\" constant=\"36\" id=\"I2w-AR-PjE\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"QTF-rn-j0f\" secondAttribute=\"trailing\" id=\"IaB-gH-YJZ\"/>\n                    <constraint firstItem=\"QTF-rn-j0f\" firstAttribute=\"leading\" secondItem=\"SE6-XM-XUK\" secondAttribute=\"leading\" id=\"KYU-hh-fSx\"/>\n                    <constraint firstItem=\"a4v-A6-gjw\" firstAttribute=\"centerX\" secondItem=\"SE6-XM-XUK\" secondAttribute=\"centerX\" id=\"kyl-71-smG\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"datePicker\" destination=\"QTF-rn-j0f\" id=\"fY2-rM-H0q\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"151.5\" y=\"-76.5\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "Example/Example/CustomDesign/SwitchCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"11762\" systemVersion=\"16C67\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"11757\"/>\n        <capability name=\"Constraints to layout margins\" minToolsVersion=\"6.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" selectionStyle=\"default\" indentationWidth=\"10\" rowHeight=\"67\" id=\"sMr-TD-BSz\" userLabel=\"Switch Cell\" customClass=\"SwitchCell\" customModule=\"Eureka\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"466\" height=\"67\"/>\n            <autoresizingMask key=\"autoresizingMask\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"sMr-TD-BSz\" id=\"5LI-gZ-vq3\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"466\" height=\"66\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <label opaque=\"NO\" userInteractionEnabled=\"NO\" contentMode=\"left\" horizontalHuggingPriority=\"251\" verticalHuggingPriority=\"251\" text=\"Just a static title\" textAlignment=\"natural\" lineBreakMode=\"tailTruncation\" baselineAdjustment=\"alignBaselines\" adjustsFontSizeToFit=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"VEC-iB-C8y\">\n                        <rect key=\"frame\" x=\"332.5\" y=\"23.5\" width=\"125.5\" height=\"20.5\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"17\"/>\n                        <nil key=\"textColor\"/>\n                        <nil key=\"highlightedColor\"/>\n                    </label>\n                    <switch opaque=\"NO\" contentMode=\"scaleToFill\" horizontalHuggingPriority=\"750\" verticalHuggingPriority=\"750\" contentHorizontalAlignment=\"center\" contentVerticalAlignment=\"center\" on=\"YES\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"lFs-g3-di0\">\n                        <rect key=\"frame\" x=\"8\" y=\"18\" width=\"51\" height=\"31\"/>\n                    </switch>\n                </subviews>\n                <constraints>\n                    <constraint firstAttribute=\"leadingMargin\" secondItem=\"lFs-g3-di0\" secondAttribute=\"leading\" id=\"7Xi-3i-w1i\"/>\n                    <constraint firstItem=\"lFs-g3-di0\" firstAttribute=\"centerY\" secondItem=\"5LI-gZ-vq3\" secondAttribute=\"centerY\" id=\"ZdS-5Y-5kO\"/>\n                    <constraint firstAttribute=\"trailingMargin\" secondItem=\"VEC-iB-C8y\" secondAttribute=\"trailing\" id=\"bav-gE-XnN\"/>\n                    <constraint firstItem=\"VEC-iB-C8y\" firstAttribute=\"centerY\" secondItem=\"5LI-gZ-vq3\" secondAttribute=\"centerY\" id=\"iI2-26-DkZ\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"switchControl\" destination=\"lFs-g3-di0\" id=\"C1f-iM-VBo\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"-273\" y=\"-252\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "Example/Example/CustomDesign/TextCell.xib",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVersion=\"11762\" systemVersion=\"16C67\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" colorMatched=\"YES\">\n    <device id=\"retina4_7\" orientation=\"portrait\">\n        <adaptation id=\"fullscreen\"/>\n    </device>\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"11757\"/>\n        <capability name=\"Constraints to layout margins\" minToolsVersion=\"6.0\"/>\n        <capability name=\"documents saved in the Xcode 8 format\" minToolsVersion=\"8.0\"/>\n    </dependencies>\n    <objects>\n        <placeholder placeholderIdentifier=\"IBFilesOwner\" id=\"-1\" userLabel=\"File's Owner\"/>\n        <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"-2\" customClass=\"UIResponder\"/>\n        <tableViewCell clipsSubviews=\"YES\" contentMode=\"scaleToFill\" selectionStyle=\"default\" indentationWidth=\"10\" rowHeight=\"199\" id=\"Aun-ko-F4t\" customClass=\"TextCell\" customModule=\"Eureka\">\n            <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"199\"/>\n            <autoresizingMask key=\"autoresizingMask\"/>\n            <tableViewCellContentView key=\"contentView\" opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" tableViewCell=\"Aun-ko-F4t\" id=\"Aaq-1L-cft\">\n                <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"375\" height=\"198.5\"/>\n                <autoresizingMask key=\"autoresizingMask\"/>\n                <subviews>\n                    <textField opaque=\"NO\" clipsSubviews=\"YES\" contentMode=\"scaleToFill\" contentHorizontalAlignment=\"left\" contentVerticalAlignment=\"center\" borderStyle=\"roundedRect\" textAlignment=\"natural\" minimumFontSize=\"17\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"cBY-oZ-Kev\" userLabel=\"textField\">\n                        <rect key=\"frame\" x=\"16\" y=\"16\" width=\"343\" height=\"60\"/>\n                        <nil key=\"textColor\"/>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"18\"/>\n                        <textInputTraits key=\"textInputTraits\"/>\n                    </textField>\n                    <textView clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" tag=\"99\" contentMode=\"scaleToFill\" scrollEnabled=\"NO\" showsHorizontalScrollIndicator=\"NO\" showsVerticalScrollIndicator=\"NO\" editable=\"NO\" text=\"Type somethng to change the text\" textAlignment=\"natural\" selectable=\"NO\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"oNs-UT-Tlz\">\n                        <rect key=\"frame\" x=\"8\" y=\"84\" width=\"359\" height=\"106.5\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"calibratedWhite\"/>\n                        <constraints>\n                            <constraint firstAttribute=\"height\" constant=\"106.5\" id=\"qgi-fV-v2S\"/>\n                        </constraints>\n                        <fontDescription key=\"fontDescription\" type=\"system\" pointSize=\"14\"/>\n                        <textInputTraits key=\"textInputTraits\" autocapitalizationType=\"sentences\"/>\n                    </textView>\n                </subviews>\n                <constraints>\n                    <constraint firstItem=\"cBY-oZ-Kev\" firstAttribute=\"leading\" secondItem=\"Aaq-1L-cft\" secondAttribute=\"leadingMargin\" constant=\"8\" id=\"HR0-UU-2qa\"/>\n                    <constraint firstAttribute=\"trailingMargin\" secondItem=\"cBY-oZ-Kev\" secondAttribute=\"trailing\" constant=\"8\" id=\"JpY-XL-v0t\"/>\n                    <constraint firstItem=\"oNs-UT-Tlz\" firstAttribute=\"top\" secondItem=\"cBY-oZ-Kev\" secondAttribute=\"bottom\" constant=\"8\" id=\"M1d-92-NIa\"/>\n                    <constraint firstItem=\"cBY-oZ-Kev\" firstAttribute=\"top\" secondItem=\"Aaq-1L-cft\" secondAttribute=\"topMargin\" constant=\"8\" id=\"XQo-fO-1yI\"/>\n                    <constraint firstAttribute=\"bottom\" secondItem=\"oNs-UT-Tlz\" secondAttribute=\"bottom\" constant=\"8\" id=\"Yvs-h1-vpn\"/>\n                    <constraint firstItem=\"oNs-UT-Tlz\" firstAttribute=\"leading\" secondItem=\"Aaq-1L-cft\" secondAttribute=\"leading\" constant=\"8\" id=\"cI9-A7-wAN\"/>\n                    <constraint firstAttribute=\"trailing\" secondItem=\"oNs-UT-Tlz\" secondAttribute=\"trailing\" constant=\"8\" id=\"d0N-Wz-4JO\"/>\n                </constraints>\n            </tableViewCellContentView>\n            <connections>\n                <outlet property=\"textField\" destination=\"cBY-oZ-Kev\" id=\"FQA-hx-ho0\"/>\n            </connections>\n            <point key=\"canvasLocation\" x=\"40.5\" y=\"41.5\"/>\n        </tableViewCell>\n    </objects>\n</document>\n"
  },
  {
    "path": "Example/Example/CustomRows/ImageRow/ImagePickerController.swift",
    "content": "//  ImagePickerController.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport Eureka\n\n/// Selector Controller used to pick an image\nopen class ImagePickerController : UIImagePickerController, TypedRowControllerType, UIImagePickerControllerDelegate, UINavigationControllerDelegate {\n    \n    /// The row that pushed or presented this controller\n    public var row: RowOf<UIImage>!\n    \n    /// A closure to be called when the controller disappears.\n    public var onDismissCallback : ((UIViewController) -> ())?\n    \n    open override func viewDidLoad() {\n        super.viewDidLoad()\n        delegate = self\n    }\n\n    open func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {\n        (row as? ImageRow)?.imageURL = info[.referenceURL] as? URL\n        row.value = info[.originalImage] as? UIImage\n        onDismissCallback?(self)\n    }\n    \n    open func imagePickerControllerDidCancel(_ picker: UIImagePickerController){\n        onDismissCallback?(self)\n    }\n}\n\n"
  },
  {
    "path": "Example/Example/CustomRows/ImageRow/ImageRow.swift",
    "content": "//  ImageRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport Eureka\n\npublic struct ImageRowSourceTypes : OptionSet {\n    \n    public let rawValue: Int\n    public var imagePickerControllerSourceTypeRawValue: Int { return self.rawValue >> 1 }\n    \n    public init(rawValue: Int) { self.rawValue = rawValue }\n    init(_ sourceType: UIImagePickerController.SourceType) { self.init(rawValue: 1 << sourceType.rawValue) }\n    \n    public static let PhotoLibrary = ImageRowSourceTypes(.photoLibrary)\n    public static let Camera = ImageRowSourceTypes(.camera)\n    public static let SavedPhotosAlbum = ImageRowSourceTypes(.savedPhotosAlbum)\n    public static let All: ImageRowSourceTypes = [Camera, PhotoLibrary, SavedPhotosAlbum]\n    \n}\n\nextension ImageRowSourceTypes {\n    \n// MARK: Helpers\n    \n    var localizedString: String {\n        switch self {\n        case ImageRowSourceTypes.Camera:\n            return \"Take photo\"\n        case ImageRowSourceTypes.PhotoLibrary:\n            return \"Photo Library\"\n        case ImageRowSourceTypes.SavedPhotosAlbum:\n            return \"Saved Photos\"\n        default:\n            return \"\"\n        }\n    }\n}\n\npublic enum ImageClearAction {\n    case no\n    case yes(style: UIAlertAction.Style)\n}\n\n//MARK: Row\n\nopen class _ImageRow<Cell: CellType>: OptionsRow<Cell>, PresenterRowType where Cell: BaseCell, Cell.Value == UIImage {\n    \n    public typealias PresenterRow = ImagePickerController\n    \n    /// Defines how the view controller will be presented, pushed, etc.\n    open var presentationMode: PresentationMode<PresenterRow>?\n    \n    /// Will be called before the presentation occurs.\n    open var onPresentCallback: ((FormViewController, PresenterRow) -> Void)?\n\n    open var sourceTypes: ImageRowSourceTypes\n    open internal(set) var imageURL: URL?\n    open var clearAction = ImageClearAction.yes(style: .destructive)\n    \n    private var _sourceType = UIImagePickerController.SourceType.camera\n    \n    public required init(tag: String?) {\n        sourceTypes = .All\n        super.init(tag: tag)\n        presentationMode = .presentModally(controllerProvider: ControllerProvider.callback { return ImagePickerController() }, onDismiss: { [weak self] vc in\n            self?.select()\n            vc.dismiss(animated: true)\n            })\n        self.displayValueFor = nil\n    }\n    \n    // copy over the existing logic from the SelectorRow\n    func displayImagePickerController(_ sourceType: UIImagePickerController.SourceType) {\n        if let presentationMode = presentationMode, !isDisabled {\n            if let controller = presentationMode.makeController(){\n                controller.row = self\n                controller.sourceType = sourceType\n                onPresentCallback?(cell.formViewController()!, controller)\n                presentationMode.present(controller, row: self, presentingController: cell.formViewController()!)\n            } else {\n                _sourceType = sourceType\n                presentationMode.present(nil, row: self, presentingController: cell.formViewController()!)\n            }\n        }\n    }\n    \n    /// Extends `didSelect` method\n    /// Selecting the Image Row cell will open a popup to choose where to source the photo from,\n    /// based on the `sourceTypes` configured and the available sources.\n    open override func customDidSelect() {\n        guard !isDisabled else {\n            super.customDidSelect()\n            return\n        }\n        deselect()\n        \n        var availableSources: ImageRowSourceTypes = []\n            \n        if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {\n            let _ = availableSources.insert(.PhotoLibrary)\n        }\n        if UIImagePickerController.isSourceTypeAvailable(.camera) {\n            let _ = availableSources.insert(.Camera)\n        }\n        if UIImagePickerController.isSourceTypeAvailable(.savedPhotosAlbum) {\n            let _ = availableSources.insert(.SavedPhotosAlbum)\n        }\n\n        sourceTypes.formIntersection(availableSources)\n        \n        if sourceTypes.isEmpty {\n            super.customDidSelect()\n            guard let presentationMode = presentationMode else { return }\n            if let controller = presentationMode.makeController() {\n                controller.row = self\n                controller.title = selectorTitle ?? controller.title\n                onPresentCallback?(cell.formViewController()!, controller)\n                presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n            } else {\n                presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n            }\n            return\n        }\n        \n        // Now that we know the number of sources aren't empty, let the user select the source\n        let sourceActionSheet = UIAlertController(title: nil, message: selectorTitle, preferredStyle: .actionSheet)\n        guard let tableView = cell.formViewController()?.tableView  else { fatalError() }\n        if let popView = sourceActionSheet.popoverPresentationController {\n            popView.sourceView = tableView\n            popView.sourceRect = tableView.convert(cell.accessoryView?.frame ?? cell.contentView.frame, from: cell)\n        }\n        createOptionsForAlertController(sourceActionSheet)\n        if case .yes(let style) = clearAction, value != nil {\n            let clearPhotoOption = UIAlertAction(title: NSLocalizedString(\"Clear Photo\", comment: \"\"), style: style, handler: { [weak self] _ in\n                self?.value = nil\n                self?.imageURL = nil\n                self?.updateCell()\n                })\n            sourceActionSheet.addAction(clearPhotoOption)\n        }\n        if sourceActionSheet.actions.count == 1 {\n            if let imagePickerSourceType = UIImagePickerController.SourceType(rawValue: sourceTypes.imagePickerControllerSourceTypeRawValue) {\n                displayImagePickerController(imagePickerSourceType)\n            }\n        } else {\n            let cancelOption = UIAlertAction(title: NSLocalizedString(\"Cancel\", comment: \"\"), style: .cancel, handler:nil)\n            sourceActionSheet.addAction(cancelOption)\n            if let presentingViewController = cell.formViewController() {\n                presentingViewController.present(sourceActionSheet, animated: true)\n            }\n        }\n    }\n    \n    /**\n     Prepares the pushed row setting its title and completion callback.\n     */\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as? PresenterRow else { return }\n        rowVC.title = selectorTitle ?? rowVC.title\n        rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback\n        onPresentCallback?(cell.formViewController()!, rowVC)\n        rowVC.row = self\n        rowVC.sourceType = _sourceType\n    }\n    \n    open override func customUpdateCell() {\n        super.customUpdateCell()\n        \n        cell.accessoryType = .none\n        cell.editingAccessoryView = .none\n        \n        if let image = self.value {\n            let imageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 44, height: 44))\n            imageView.contentMode = .scaleAspectFill\n            imageView.image = image\n            imageView.clipsToBounds = true\n            \n            cell.accessoryView = imageView\n            cell.editingAccessoryView = imageView\n        } else {\n            cell.accessoryView = nil\n            cell.editingAccessoryView = nil\n        }\n    }\n    \n\n}\n\nextension _ImageRow {\n    \n//MARK: Helpers\n    \n    func createOptionForAlertController(_ alertController: UIAlertController, sourceType: ImageRowSourceTypes) {\n        guard let pickerSourceType = UIImagePickerController.SourceType(rawValue: sourceType.imagePickerControllerSourceTypeRawValue), sourceTypes.contains(sourceType) else { return }\n        let option = UIAlertAction(title: NSLocalizedString(sourceType.localizedString, comment: \"\"), style: .default, handler: { [weak self] _ in\n            self?.displayImagePickerController(pickerSourceType)\n        })\n        alertController.addAction(option)\n    }\n    \n    func createOptionsForAlertController(_ alertController: UIAlertController) {\n        createOptionForAlertController(alertController, sourceType: .Camera)\n        createOptionForAlertController(alertController, sourceType: .PhotoLibrary)\n        createOptionForAlertController(alertController, sourceType: .SavedPhotosAlbum)\n    }\n}\n\n/// A selector row where the user can pick an image\npublic final class ImageRow : _ImageRow<PushSelectorCell<UIImage>>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n"
  },
  {
    "path": "Example/Example/Helpers/FloatLabelTextField.swift",
    "content": "//\n//  FloatLabelTextField.swift\n//  FloatLabelFields\n//\n//  Created by Fahim Farook on 28/11/14.\n//  Copyright (c) 2014 RookSoft Ltd. All rights reserved.\n//\n//  Original Concept by Matt D. Smith\n//  http://dribbble.com/shots/1254439--GIF-Mobile-Form-Interaction?list=users\n//\n//  Objective-C version by Jared Verdi\n//  https://github.com/jverdi/JVFloatLabeledTextField\n//\n\nimport UIKit\n\n@IBDesignable public class FloatLabelTextField: UITextField {\n\tlet animationDuration = 0.3\n\tvar title = UILabel()\n\t\n\t// MARK:- Properties\n\toverride public var accessibilityLabel:String! {\n\t\tget {\n\t\t\tif text?.isEmpty ?? true {\n\t\t\t\treturn title.text\n\t\t\t} else {\n\t\t\t\treturn text\n\t\t\t}\n\t\t}\n\t\tset {\n\t\t\tself.accessibilityLabel = newValue\n\t\t}\n\t}\n\t\n\toverride public var placeholder:String? {\n\t\tdidSet {\n\t\t\ttitle.text = placeholder\n\t\t\ttitle.sizeToFit()\n\t\t}\n\t}\n\t\n\toverride public var attributedPlaceholder:NSAttributedString? {\n\t\tdidSet {\n\t\t\ttitle.text = attributedPlaceholder?.string\n\t\t\ttitle.sizeToFit()\n\t\t}\n\t}\n\t\n\tvar titleFont: UIFont = .systemFont(ofSize: 12.0) {\n\t\tdidSet {\n\t\t\ttitle.font = titleFont\n\t\t\ttitle.sizeToFit()\n\t\t}\n\t}\n\t\n\t@IBInspectable var hintYPadding:CGFloat = 0.0\n\n\t@IBInspectable var titleYPadding:CGFloat = 0.0 {\n\t\tdidSet {\n\t\t\tvar r = title.frame\n\t\t\tr.origin.y = titleYPadding\n\t\t\ttitle.frame = r\n\t\t}\n\t}\n\t\n\t@IBInspectable var titleTextColour:UIColor = .gray {\n\t\tdidSet {\n\t\t\tif !isFirstResponder {\n\t\t\t\ttitle.textColor = titleTextColour\n\t\t\t}\n\t\t}\n\t}\n\t\n\t@IBInspectable var titleActiveTextColour:UIColor! {\n\t\tdidSet {\n\t\t\tif isFirstResponder {\n\t\t\t\ttitle.textColor = titleActiveTextColour\n\t\t\t}\n\t\t}\n\t}\n\t\n\t// MARK:- Init\n\trequired public init?(coder aDecoder:NSCoder) {\n\t\tsuper.init(coder:aDecoder)\n\t\tsetup()\n\t}\n\t\n\toverride init(frame:CGRect) {\n\t\tsuper.init(frame:frame)\n\t\tsetup()\n\t}\n\t\n\t// MARK:- Overrides\n\toverride public func layoutSubviews() {\n\t\tsuper.layoutSubviews()\n\t\tsetTitlePositionForTextAlignment()\n\t\tlet isResp = isFirstResponder\n\t\tif isResp && !(text?.isEmpty ?? true) {\n\t\t\ttitle.textColor = titleActiveTextColour\n\t\t} else {\n\t\t\ttitle.textColor = titleTextColour\n\t\t}\n\t\t// Should we show or hide the title label?\n\t\tif text?.isEmpty ?? true {\n\t\t\t// Hide\n\t\t\thideTitle(isResp)\n\t\t} else {\n\t\t\t// Show\n\t\t\tshowTitle(isResp)\n\t\t}\n\t}\n\t\n\toverride public func textRect(forBounds bounds:CGRect) -> CGRect {\n\t\tvar r = super.textRect(forBounds: bounds)\n\t\tif !(text?.isEmpty ?? true){\n\t\t\tvar top = ceil(title.font.lineHeight + hintYPadding)\n\t\t\ttop = min(top, maxTopInset())\n            r = r.inset(by: UIEdgeInsets(top: top, left: 0.0, bottom: 0.0, right: 0.0))\n\t\t}\n\t\treturn r.integral\n\t}\n\t\n\toverride public func editingRect(forBounds bounds:CGRect) -> CGRect {\n\t\tvar r = super.editingRect(forBounds: bounds)\n\t\tif !(text?.isEmpty ?? true) {\n\t\t\tvar top = ceil(title.font.lineHeight + hintYPadding)\n\t\t\ttop = min(top, maxTopInset())\n            r = r.inset(by: UIEdgeInsets(top: top, left: 0.0, bottom: 0.0, right: 0.0))\n\t\t}\n\t\treturn r.integral\n\t}\n\t\n\toverride public func clearButtonRect(forBounds bounds:CGRect) -> CGRect {\n\t\tvar r = super.clearButtonRect(forBounds: bounds)\n\t\tif !(text?.isEmpty ?? true) {\n\t\t\tvar top = ceil(title.font.lineHeight + hintYPadding)\n\t\t\ttop = min(top, maxTopInset())\n\t\t\tr = CGRect(x:r.origin.x, y:r.origin.y + (top * 0.5), width:r.size.width, height:r.size.height)\n\t\t}\n\t\treturn r.integral\n\t}\n\t\n\t// MARK:- Public Methods\n\t\n\t// MARK:- Private Methods\n\tprivate func setup() {\n        borderStyle = .none\n\t\ttitleActiveTextColour = tintColor\n\t\t// Set up title label\n\t\ttitle.alpha = 0.0\n\t\ttitle.font = titleFont\n\t\ttitle.textColor = titleTextColour\n\t\tif let str = placeholder, !str.isEmpty {\n            title.text = str\n            title.sizeToFit()\n\t\t}\n\t\tself.addSubview(title)\n\t}\n\n\tprivate func maxTopInset()->CGFloat {\n\t\treturn max(0, floor(bounds.size.height - (font?.lineHeight ?? 0) - 4.0))\n\t}\n\t\n\tprivate func setTitlePositionForTextAlignment() {\n\t\tlet r = textRect(forBounds: bounds)\n\t\tvar x = r.origin.x\n\t\tif textAlignment == .center {\n\t\t\tx = r.origin.x + (r.size.width * 0.5) - title.frame.size.width\n\t\t} else if textAlignment == .right {\n\t\t\tx = r.origin.x + r.size.width - title.frame.size.width\n\t\t}\n\t\ttitle.frame = CGRect(x:x, y:title.frame.origin.y, width:title.frame.size.width, height:title.frame.size.height)\n\t}\n\t\n\tprivate func showTitle(_ animated:Bool) {\n\t\tlet dur = animated ? animationDuration : 0\n        UIView.animate(withDuration: dur, delay:0, options: [.beginFromCurrentState, .curveEaseOut], animations:{\n\t\t\t\t// Animation\n\t\t\t\tself.title.alpha = 1.0\n\t\t\t\tvar r = self.title.frame\n\t\t\t\tr.origin.y = self.titleYPadding\n\t\t\t\tself.title.frame = r\n\t\t\t})\n\t}\n\t\n\tprivate func hideTitle(_ animated:Bool) {\n\t\tlet dur = animated ? animationDuration : 0\n\t\tUIView.animate(withDuration: dur, delay:0, options: [.beginFromCurrentState, .curveEaseIn], animations:{\n\t\t\t// Animation\n\t\t\tself.title.alpha = 0.0\n\t\t\tvar r = self.title.frame\n\t\t\tr.origin.y = self.title.font.lineHeight + self.hintYPadding\n\t\t\tself.title.frame = r\n\t\t\t})\n\t}\n}\n"
  },
  {
    "path": "Example/Example/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>Eureka</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>5.0.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>NSCameraUsageDescription</key>\n\t<string>ImageRow example</string>\n\t<key>NSPhotoLibraryUsageDescription</key>\n\t<string>Show ImageRow example</string>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UIRequiredDeviceCapabilities</key>\n\t<array>\n\t\t<string>armv7</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example/Example/ViewController.swift",
    "content": "//  ViewController.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport UIKit\nimport Eureka\n\n//MARK: HomeViewController\n\nclass HomeViewController : FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n\n        ImageRow.defaultCellUpdate = { cell, row in\n           cell.accessoryView?.layer.cornerRadius = 17\n           cell.accessoryView?.frame = CGRect(x: 0, y: 0, width: 34, height: 34)\n        }\n\n        form +++\n\n            Section() {\n                $0.header = HeaderFooterView<EurekaLogoView>(.class)\n            }\n\n                <<< ButtonRow(\"Rows\") {\n                        $0.title = $0.tag\n                        $0.presentationMode = .segueName(segueName: \"RowsExampleViewControllerSegue\", onDismiss: nil)\n                    }\n\n                <<< ButtonRow(\"Native iOS Event Form\") { row in\n                        row.title = row.tag\n                        row.presentationMode = .segueName(segueName: \"NativeEventsFormNavigationControllerSegue\", onDismiss:{  vc in vc.dismiss(animated: true) })\n                    }\n\n                <<< ButtonRow(\"Accesory View Navigation\") { (row: ButtonRow) in\n                        row.title = row.tag\n                        row.presentationMode = .segueName(segueName: \"AccesoryViewControllerSegue\", onDismiss: nil)\n                    }\n\n                <<< ButtonRow(\"Custom Cells\") { (row: ButtonRow) -> () in\n                        row.title = row.tag\n                        row.presentationMode = .segueName(segueName: \"CustomCellsControllerSegue\", onDismiss: nil)\n                    }\n\n                <<< ButtonRow(\"Customization of rows with text input\") { (row: ButtonRow) -> Void in\n                        row.title = row.tag\n                        row.presentationMode = .segueName(segueName: \"FieldCustomizationControllerSegue\", onDismiss: nil)\n                    }\n\n                <<< ButtonRow(\"Hidden rows\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"HiddenRowsControllerSegue\", onDismiss: nil)\n                    }\n\n                <<< ButtonRow(\"Disabled rows\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"DisabledRowsControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Formatters\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"FormattersControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Inline rows\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"InlineRowsControllerSegue\", onDismiss: nil)\n                }\n                <<< ButtonRow(\"List Sections\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"ListSectionsControllerSegue\", onDismiss: nil)\n                }\n                <<< ButtonRow(\"Validations\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"ValidationsControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Custom Design\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"CustomDesignControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Multivalued Sections\") { (row: ButtonRow) -> Void in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"MultivaluedSectionsControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Swipe Actions\") { (row: ButtonRow) -> Void in\n                  row.title = row.tag\n                  row.presentationMode = .segueName(segueName: \"SwipeActionsControllerSegue\", onDismiss: nil)\n                }\n\n                <<< ButtonRow(\"Plain Table View Style\") { (row: ButtonRow) in\n                    row.title = row.tag\n                    row.presentationMode = .segueName(segueName: \"PlainTableViewStyleViewControllerSegue\", onDismiss: nil)\n                }\n\n\n        +++ Section()\n                <<< ButtonRow() { (row: ButtonRow) -> Void in\n                   row.title = \"About\"\n                }\n                .onCellSelection { [weak self] (cell, row) in\n                    self?.showAlert()\n                }\n\n    }\n\n\n    @IBAction func showAlert() {\n        let alertController = UIAlertController(title: \"OnCellSelection\", message: \"Button Row Action\", preferredStyle: .alert)\n        let defaultAction = UIAlertAction(title: \"OK\", style: .default, handler: nil)\n        alertController.addAction(defaultAction)\n        present(alertController, animated: true)\n\n    }\n\n}\n\n//MARK: Emoji\n\ntypealias Emoji = String\nlet 👦🏼 = \"👦🏼\", 🍐 = \"🍐\", 💁🏻 = \"💁🏻\", 🐗 = \"🐗\", 🐼 = \"🐼\", 🐻 = \"🐻\", 🐖 = \"🐖\", 🐡 = \"🐡\"\n\n\nclass EurekaLogoView: UIView {\n\n    override init(frame: CGRect) {\n        super.init(frame: frame)\n        let imageView = UIImageView(image: UIImage(named: \"Eureka\"))\n        imageView.frame = CGRect(x: 0, y: 0, width: 320, height: 130)\n        imageView.autoresizingMask = .flexibleWidth\n        self.frame = CGRect(x: 0, y: 0, width: 320, height: 130)\n        imageView.contentMode = .scaleAspectFit\n        addSubview(imageView)\n    }\n\n    required init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n}\n"
  },
  {
    "path": "Example/UITests/FieldRowUITests.swift",
    "content": "//  ExampleUITests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n\nclass FieldRowUITests: XCTestCase {\n        \n    override func setUp() {\n        super.setUp()\n        \n        // Put setup code here. This method is called before the invocation of each test method in the class.\n        \n        // In UI tests it is usually best to stop immediately when a failure occurs.\n        continueAfterFailure = false\n        // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method.\n        XCUIApplication().launch()\n\n        // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this.\n    }\n    \n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n    \n    func testDecimalRowWithFormatterDuringInput() {\n        // Use XCTAssert and related functions to verify your tests produce the correct results.\n        \n        let app = XCUIApplication()\n        let tablesQuery = app.tables\n        \n        // navigte to Rows view controller\n        tablesQuery.cells.staticTexts[\"Rows\"].tap()\n        \n        \n        // get Decimal row text field\n        let decimalRowTextFieldElement = tablesQuery.cells.containing(.staticText, identifier:\"DecimalRow\").children(matching: .textField).element\n        \n        // chack initial value\n        XCTAssertEqual(decimalRowTextFieldElement.value as? String, decimalFormatter.editingString(for: Double(5)), \"Initial Decimal Row value is wrong, should be 5,00 or 5.00\")\n        \n        \n        // check that delete keyboard worlks properly\n        decimalRowTextFieldElement.tap()\n        let deleteKey = app.keys[\"Delete\"]\n        deleteKey.tap()\n        XCTAssertEqual(decimalRowTextFieldElement.value as? String, decimalFormatter.editingString(for: Double(0.5)), \"Decimal Row value is wrong, should be 0,50 or 0.50\")\n        \n        // check empty value\n        for _ in 1...2 { deleteKey.tap() }\n        //should be 0,00\n        XCTAssertEqual(decimalRowTextFieldElement.value as? String, decimalFormatter.editingString(for: Double(0)), \"Decimal Row value is wrong, should be 0,00 or 0.00\")\n        \n        \n        // check result when entering digits\n        decimalRowTextFieldElement.typeText(\"5678\")\n        // Should be 56,78\n        XCTAssertEqual(decimalRowTextFieldElement.value as? String, decimalFormatter.editingString(for: Double(56.78)), \"Decimal Row value is wrong, should be 56,78 or 56.78\")\n        \n        // one more check...\n        decimalRowTextFieldElement.typeText(\"9\")\n        // SHOULD BE 567,89\n        XCTAssertEqual(decimalRowTextFieldElement.value as? String, decimalFormatter.editingString(for: Double(567.89)), \"Decimal Row value is wrong, should be 567,89 or 567.89\")\n    }\n    \n    \n    func testIntRowWithFormatterButNotDUringInput() {\n        \n        let app = XCUIApplication()\n        let tablesQuery = app.tables\n        tablesQuery.cells.staticTexts[\"Rows\"].tap()\n        \n        let textField = tablesQuery.cells.containing(.staticText, identifier:\"IntRow\").children(matching: .textField).element\n        \n        // chack initial value\n        XCTAssertEqual(textField.value as? String, intFormatter.string(for: Int(2015)), \"Initial Int Row value is wrong, should be 2,015 or 2.015\")\n        \n        textField.tap()\n        // should be 2015\n        XCTAssertEqual(textField.value as? String, \"2015\", \"Editing Initial Int Row value is wrong, should be 2015\")\n    \n        let deleteKey = app.keys[\"Delete\"]\n        \n        deleteKey.tap()\n        // sould be 201\n        XCTAssertEqual(textField.value as? String, intFormatter.string(for: Int(201)), \"Int Row value is wrong, should be 201\")\n        \n        deleteKey.tap()\n        deleteKey.tap()\n        deleteKey.tap()\n        // should be empty\n        XCTAssertEqual(textField.value as? String, \"\", \"Int Row value is wrong, should be \\\"\\\"\")\n        \n        \n        textField.typeText(\"1\")\n        // should be 1\n        XCTAssertEqual(textField.value as? String, intFormatter.string(for: Int(1)), \"Int Row value is wrong, should be 1\")\n        \n        \n        textField.typeText(\"2345\")\n        // regign firest responder\n        app.toolbars.buttons[\"Done\"].tap()\n        \n    \n        // should be 12,345\n        XCTAssertEqual(textField.value as? String, intFormatter.string(for: Int(12345)), \"Int Row value is wrong, should be 12,345 or 12.345\")\n    }\n    \n    \n    \n    //MARK: Helpers\n\n    lazy var decimalFormatter: NumberFormatter = {\n        let numberFormatter = NumberFormatter()\n        numberFormatter.locale = Locale.current\n        numberFormatter.numberStyle = .decimal\n        numberFormatter.minimumFractionDigits = 2\n        return numberFormatter\n    }()\n    \n    lazy var intFormatter: NumberFormatter = {\n        let numberFormatter = NumberFormatter()\n        numberFormatter.locale = Locale.current\n        numberFormatter.numberStyle = .decimal\n        numberFormatter.minimumFractionDigits = 0\n        numberFormatter.maximumFractionDigits = 0\n        return numberFormatter\n    }()\n\n    \n}\n"
  },
  {
    "path": "Example/UITests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>1.0</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t2837E2A01BA3A5A800A1952C /* FloatLabelTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2837E29E1BA3A5A800A1952C /* FloatLabelTextField.swift */; };\n\t\t284D28B61E49121E00BB38E7 /* DatePickerCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 284D28B51E49121E00BB38E7 /* DatePickerCell.xib */; };\n\t\t284D28B81E4917A000BB38E7 /* SwitchCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 284D28B71E4917A000BB38E7 /* SwitchCell.xib */; };\n\t\t284D28BA1E491FEF00BB38E7 /* TextCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 284D28B91E491FEF00BB38E7 /* TextCell.xib */; };\n\t\t285F2B441BB79B86005991BA /* MapKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 285F2B431BB79B86005991BA /* MapKit.framework */; };\n\t\t287A143F1D99A96100FFE6EB /* ImagePickerController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287A143D1D99A96100FFE6EB /* ImagePickerController.swift */; };\n\t\t287A14401D99A96100FFE6EB /* ImageRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 287A143E1D99A96100FFE6EB /* ImageRow.swift */; };\n\t\t28C777241BA14A52000ED936 /* Eureka.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 51729E471B9A5841004A00EB /* Eureka.framework */; };\n\t\t28C777251BA14A52000ED936 /* Eureka.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 51729E471B9A5841004A00EB /* Eureka.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };\n\t\t28CD97C21BB32F0E00AFDA67 /* EurekaSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28CD97C01BB32F0E00AFDA67 /* EurekaSectionHeader.xib */; };\n\t\t28E8554C1B9EA46F004E5189 /* FieldRowUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 28E8554A1B9EA400004E5189 /* FieldRowUITests.swift */; };\n\t\t51729E1E1B9A54F1004A00EB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51729E1D1B9A54F1004A00EB /* AppDelegate.swift */; };\n\t\t51729E201B9A54F1004A00EB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51729E1F1B9A54F1004A00EB /* ViewController.swift */; };\n\t\t51729E231B9A54F1004A00EB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51729E211B9A54F1004A00EB /* Main.storyboard */; };\n\t\t51729E251B9A54F1004A00EB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 51729E241B9A54F1004A00EB /* Assets.xcassets */; };\n\t\t51729E281B9A54F1004A00EB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 51729E261B9A54F1004A00EB /* LaunchScreen.storyboard */; };\n\t\t51729E6E1B9A6601004A00EB /* CustomCells.swift in Sources */ = {isa = PBXBuildFile; fileRef = 51729E6D1B9A6601004A00EB /* CustomCells.swift */; };\n\t\t51729E711B9A660A004A00EB /* WeekDaysCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 51729E6F1B9A660A004A00EB /* WeekDaysCell.xib */; };\n\t\t8F32504F205AAA93006AF0A6 /* RowsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F32504E205AAA93006AF0A6 /* RowsExample.swift */; };\n\t\t8F325051205AAB35006AF0A6 /* CustomCellsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325050205AAB35006AF0A6 /* CustomCellsViewController.swift */; };\n\t\t8F325053205AAB6F006AF0A6 /* FieldRowCustomizationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325052205AAB6F006AF0A6 /* FieldRowCustomizationController.swift */; };\n\t\t8F325055205AABA6006AF0A6 /* NavigationAccessoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325054205AABA6006AF0A6 /* NavigationAccessoryController.swift */; };\n\t\t8F325057205AABDB006AF0A6 /* NativeEventExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325056205AABDB006AF0A6 /* NativeEventExample.swift */; };\n\t\t8F325059205AAC06006AF0A6 /* HiddenRowsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325058205AAC06006AF0A6 /* HiddenRowsExample.swift */; };\n\t\t8F32505B205AAC2A006AF0A6 /* DisabledRowsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F32505A205AAC2A006AF0A6 /* DisabledRowsExample.swift */; };\n\t\t8F32505D205AAC68006AF0A6 /* FormatterExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F32505C205AAC68006AF0A6 /* FormatterExample.swift */; };\n\t\t8F32505F205AAC8E006AF0A6 /* InlineRowsExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F32505E205AAC8E006AF0A6 /* InlineRowsExample.swift */; };\n\t\t8F325061205AACB9006AF0A6 /* ListSectionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325060205AACB9006AF0A6 /* ListSectionsController.swift */; };\n\t\t8F325063205AACF4006AF0A6 /* ValidationsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325062205AACF4006AF0A6 /* ValidationsController.swift */; };\n\t\t8F325065205AAD23006AF0A6 /* CustomDesignController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325064205AAD23006AF0A6 /* CustomDesignController.swift */; };\n\t\t8F325067205AAD7A006AF0A6 /* MultivaluedExamples.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325066205AAD7A006AF0A6 /* MultivaluedExamples.swift */; };\n\t\t8F325069205AAF1E006AF0A6 /* SwipeActionsController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F325068205AAF1E006AF0A6 /* SwipeActionsController.swift */; };\n\t\t8F32506B205AAF66006AF0A6 /* PlainTableViewExample.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8F32506A205AAF66006AF0A6 /* PlainTableViewExample.swift */; };\n\t\tD4ACF9132074B52200AEA952 /* EmojiCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D4ACF9122074B52200AEA952 /* EmojiCell.xib */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXContainerItemProxy section */\n\t\t28C777261BA14A52000ED936 /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729E411B9A5841004A00EB /* Eureka.xcodeproj */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 51729DEA1B9A4F5E004A00EB;\n\t\t\tremoteInfo = Eureka;\n\t\t};\n\t\t51729E2F1B9A54F1004A00EB /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729E121B9A54F1004A00EB /* Project object */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 51729E191B9A54F1004A00EB;\n\t\t\tremoteInfo = Example;\n\t\t};\n\t\t51729E461B9A5841004A00EB /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729E411B9A5841004A00EB /* Eureka.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 51729DEB1B9A4F5E004A00EB;\n\t\t\tremoteInfo = Eureka;\n\t\t};\n\t\t51729E481B9A5841004A00EB /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729E411B9A5841004A00EB /* Eureka.xcodeproj */;\n\t\t\tproxyType = 2;\n\t\t\tremoteGlobalIDString = 51729DF51B9A4F5E004A00EB;\n\t\t\tremoteInfo = EurekaTests;\n\t\t};\n\t\tBF4298981BA0997D001D107B /* PBXContainerItemProxy */ = {\n\t\t\tisa = PBXContainerItemProxy;\n\t\t\tcontainerPortal = 51729E411B9A5841004A00EB /* Eureka.xcodeproj */;\n\t\t\tproxyType = 1;\n\t\t\tremoteGlobalIDString = 51729DEA1B9A4F5E004A00EB;\n\t\t\tremoteInfo = Eureka;\n\t\t};\n/* End PBXContainerItemProxy section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t28C777281BA14A52000ED936 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t\t28C777251BA14A52000ED936 /* Eureka.framework in Embed Frameworks */,\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t2837E29E1BA3A5A800A1952C /* FloatLabelTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; path = FloatLabelTextField.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t284D28B51E49121E00BB38E7 /* DatePickerCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = DatePickerCell.xib; path = Example/CustomDesign/DatePickerCell.xib; sourceTree = \"<group>\"; };\n\t\t284D28B71E4917A000BB38E7 /* SwitchCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = SwitchCell.xib; path = Example/CustomDesign/SwitchCell.xib; sourceTree = \"<group>\"; };\n\t\t284D28B91E491FEF00BB38E7 /* TextCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = TextCell.xib; path = Example/CustomDesign/TextCell.xib; sourceTree = \"<group>\"; };\n\t\t285F2B431BB79B86005991BA /* MapKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MapKit.framework; path = System/Library/Frameworks/MapKit.framework; sourceTree = SDKROOT; };\n\t\t287A143D1D99A96100FFE6EB /* ImagePickerController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImagePickerController.swift; path = Example/CustomRows/ImageRow/ImagePickerController.swift; sourceTree = \"<group>\"; };\n\t\t287A143E1D99A96100FFE6EB /* ImageRow.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ImageRow.swift; path = Example/CustomRows/ImageRow/ImageRow.swift; sourceTree = \"<group>\"; };\n\t\t28CD97C11BB32F0E00AFDA67 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Example/Base.lproj/EurekaSectionHeader.xib; sourceTree = \"<group>\"; };\n\t\t28E8554A1B9EA400004E5189 /* FieldRowUITests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = FieldRowUITests.swift; path = Example/UITests/FieldRowUITests.swift; sourceTree = SOURCE_ROOT; };\n\t\t51729E1A1B9A54F1004A00EB /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t51729E1D1B9A54F1004A00EB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = Example/AppDelegate.swift; sourceTree = \"<group>\"; };\n\t\t51729E1F1B9A54F1004A00EB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = ViewController.swift; path = Example/ViewController.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t51729E221B9A54F1004A00EB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t51729E241B9A54F1004A00EB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Assets.xcassets; path = Example/Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t51729E271B9A54F1004A00EB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t51729E291B9A54F1004A00EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = Info.plist; path = Example/Info.plist; sourceTree = \"<group>\"; };\n\t\t51729E2E1B9A54F1004A00EB /* ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t51729E341B9A54F1004A00EB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist; name = Info.plist; path = Example/UITests/Info.plist; sourceTree = \"<group>\"; };\n\t\t51729E411B9A5841004A00EB /* Eureka.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = \"wrapper.pb-project\"; path = Eureka.xcodeproj; sourceTree = \"<group>\"; };\n\t\t51729E6D1B9A6601004A00EB /* CustomCells.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; lineEnding = 0; name = CustomCells.swift; path = Example/CustomCells.swift; sourceTree = \"<group>\"; xcLanguageSpecificationIdentifier = xcode.lang.swift; };\n\t\t51729E701B9A660A004A00EB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Example/Base.lproj/WeekDaysCell.xib; sourceTree = \"<group>\"; };\n\t\t8F32504E205AAA93006AF0A6 /* RowsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RowsExample.swift; sourceTree = \"<group>\"; };\n\t\t8F325050205AAB35006AF0A6 /* CustomCellsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomCellsViewController.swift; sourceTree = \"<group>\"; };\n\t\t8F325052205AAB6F006AF0A6 /* FieldRowCustomizationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FieldRowCustomizationController.swift; sourceTree = \"<group>\"; };\n\t\t8F325054205AABA6006AF0A6 /* NavigationAccessoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationAccessoryController.swift; sourceTree = \"<group>\"; };\n\t\t8F325056205AABDB006AF0A6 /* NativeEventExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NativeEventExample.swift; sourceTree = \"<group>\"; };\n\t\t8F325058205AAC06006AF0A6 /* HiddenRowsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HiddenRowsExample.swift; sourceTree = \"<group>\"; };\n\t\t8F32505A205AAC2A006AF0A6 /* DisabledRowsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DisabledRowsExample.swift; sourceTree = \"<group>\"; };\n\t\t8F32505C205AAC68006AF0A6 /* FormatterExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FormatterExample.swift; sourceTree = \"<group>\"; };\n\t\t8F32505E205AAC8E006AF0A6 /* InlineRowsExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InlineRowsExample.swift; sourceTree = \"<group>\"; };\n\t\t8F325060205AACB9006AF0A6 /* ListSectionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ListSectionsController.swift; sourceTree = \"<group>\"; };\n\t\t8F325062205AACF4006AF0A6 /* ValidationsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ValidationsController.swift; sourceTree = \"<group>\"; };\n\t\t8F325064205AAD23006AF0A6 /* CustomDesignController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomDesignController.swift; sourceTree = \"<group>\"; };\n\t\t8F325066205AAD7A006AF0A6 /* MultivaluedExamples.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MultivaluedExamples.swift; sourceTree = \"<group>\"; };\n\t\t8F325068205AAF1E006AF0A6 /* SwipeActionsController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeActionsController.swift; sourceTree = \"<group>\"; };\n\t\t8F32506A205AAF66006AF0A6 /* PlainTableViewExample.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PlainTableViewExample.swift; sourceTree = \"<group>\"; };\n\t\tD4ACF9122074B52200AEA952 /* EmojiCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = EmojiCell.xib; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t51729E171B9A54F1004A00EB /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t285F2B441BB79B86005991BA /* MapKit.framework in Frameworks */,\n\t\t\t\t28C777241BA14A52000ED936 /* Eureka.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729E2B1B9A54F1004A00EB /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t2837E29D1BA3A5A800A1952C /* Helpers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2837E29E1BA3A5A800A1952C /* FloatLabelTextField.swift */,\n\t\t\t);\n\t\t\tname = Helpers;\n\t\t\tpath = Example/Helpers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t284D28AE1E48C27300BB38E7 /* Custom Design */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t284D28B71E4917A000BB38E7 /* SwitchCell.xib */,\n\t\t\t\t284D28B51E49121E00BB38E7 /* DatePickerCell.xib */,\n\t\t\t\t284D28B91E491FEF00BB38E7 /* TextCell.xib */,\n\t\t\t);\n\t\t\tname = \"Custom Design\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t285F2B451BB79BB7005991BA /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t285F2B431BB79B86005991BA /* MapKit.framework */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t287A143B1D99A91B00FFE6EB /* ImageRow */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t287A143D1D99A96100FFE6EB /* ImagePickerController.swift */,\n\t\t\t\t287A143E1D99A96100FFE6EB /* ImageRow.swift */,\n\t\t\t);\n\t\t\tname = ImageRow;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t28CD97BE1BB32EC800AFDA67 /* Custom Section Header */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t28CD97C01BB32F0E00AFDA67 /* EurekaSectionHeader.xib */,\n\t\t\t);\n\t\t\tname = \"Custom Section Header\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E111B9A54F1004A00EB = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E1C1B9A54F1004A00EB /* Example */,\n\t\t\t\t51729E311B9A54F1004A00EB /* UITests */,\n\t\t\t\t51729E1B1B9A54F1004A00EB /* Products */,\n\t\t\t\t285F2B451BB79BB7005991BA /* Supporting Files */,\n\t\t\t\t51729E411B9A5841004A00EB /* Eureka.xcodeproj */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E1B1B9A54F1004A00EB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E1A1B9A54F1004A00EB /* Example.app */,\n\t\t\t\t51729E2E1B9A54F1004A00EB /* ExampleUITests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E1C1B9A54F1004A00EB /* Example */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8F32504C205AAA4D006AF0A6 /* Controllers */,\n\t\t\t\t284D28AE1E48C27300BB38E7 /* Custom Design */,\n\t\t\t\t28CD97BE1BB32EC800AFDA67 /* Custom Section Header */,\n\t\t\t\t51729E6A1B9A657E004A00EB /* Custom Row and Cell */,\n\t\t\t\t51729E1D1B9A54F1004A00EB /* AppDelegate.swift */,\n\t\t\t\t51729E1F1B9A54F1004A00EB /* ViewController.swift */,\n\t\t\t\t51729E211B9A54F1004A00EB /* Main.storyboard */,\n\t\t\t\t51729E241B9A54F1004A00EB /* Assets.xcassets */,\n\t\t\t\t51729E261B9A54F1004A00EB /* LaunchScreen.storyboard */,\n\t\t\t\t51729E291B9A54F1004A00EB /* Info.plist */,\n\t\t\t);\n\t\t\tpath = Example;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E311B9A54F1004A00EB /* UITests */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t28E8554A1B9EA400004E5189 /* FieldRowUITests.swift */,\n\t\t\t\t51729E341B9A54F1004A00EB /* Info.plist */,\n\t\t\t);\n\t\t\tname = UITests;\n\t\t\tpath = Example/UITests;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E421B9A5841004A00EB /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E471B9A5841004A00EB /* Eureka.framework */,\n\t\t\t\t51729E491B9A5841004A00EB /* EurekaTests.xctest */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E6A1B9A657E004A00EB /* Custom Row and Cell */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t287A143B1D99A91B00FFE6EB /* ImageRow */,\n\t\t\t\t2837E29D1BA3A5A800A1952C /* Helpers */,\n\t\t\t\t51729E6F1B9A660A004A00EB /* WeekDaysCell.xib */,\n\t\t\t\tD4ACF9122074B52200AEA952 /* EmojiCell.xib */,\n\t\t\t\t51729E6D1B9A6601004A00EB /* CustomCells.swift */,\n\t\t\t);\n\t\t\tname = \"Custom Row and Cell\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t8F32504C205AAA4D006AF0A6 /* Controllers */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t8F325050205AAB35006AF0A6 /* CustomCellsViewController.swift */,\n\t\t\t\t8F325064205AAD23006AF0A6 /* CustomDesignController.swift */,\n\t\t\t\t8F32505A205AAC2A006AF0A6 /* DisabledRowsExample.swift */,\n\t\t\t\t8F325052205AAB6F006AF0A6 /* FieldRowCustomizationController.swift */,\n\t\t\t\t8F32505C205AAC68006AF0A6 /* FormatterExample.swift */,\n\t\t\t\t8F325058205AAC06006AF0A6 /* HiddenRowsExample.swift */,\n\t\t\t\t8F32505E205AAC8E006AF0A6 /* InlineRowsExample.swift */,\n\t\t\t\t8F325060205AACB9006AF0A6 /* ListSectionsController.swift */,\n\t\t\t\t8F325066205AAD7A006AF0A6 /* MultivaluedExamples.swift */,\n\t\t\t\t8F325056205AABDB006AF0A6 /* NativeEventExample.swift */,\n\t\t\t\t8F325054205AABA6006AF0A6 /* NavigationAccessoryController.swift */,\n\t\t\t\t8F32506A205AAF66006AF0A6 /* PlainTableViewExample.swift */,\n\t\t\t\t8F32504E205AAA93006AF0A6 /* RowsExample.swift */,\n\t\t\t\t8F325068205AAF1E006AF0A6 /* SwipeActionsController.swift */,\n\t\t\t\t8F325062205AACF4006AF0A6 /* ValidationsController.swift */,\n\t\t\t);\n\t\t\tname = Controllers;\n\t\t\tpath = Example/Controllers;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t51729E191B9A54F1004A00EB /* Example */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 51729E371B9A54F1004A00EB /* Build configuration list for PBXNativeTarget \"Example\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t51729E161B9A54F1004A00EB /* Sources */,\n\t\t\t\t51729E171B9A54F1004A00EB /* Frameworks */,\n\t\t\t\t51729E181B9A54F1004A00EB /* Resources */,\n\t\t\t\t28C777281BA14A52000ED936 /* Embed Frameworks */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\tBF4298991BA0997D001D107B /* PBXTargetDependency */,\n\t\t\t\t28C777271BA14A52000ED936 /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = Example;\n\t\t\tproductName = Example;\n\t\t\tproductReference = 51729E1A1B9A54F1004A00EB /* Example.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n\t\t51729E2D1B9A54F1004A00EB /* ExampleUITests */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 51729E3A1B9A54F1004A00EB /* Build configuration list for PBXNativeTarget \"ExampleUITests\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t51729E2A1B9A54F1004A00EB /* Sources */,\n\t\t\t\t51729E2B1B9A54F1004A00EB /* Frameworks */,\n\t\t\t\t51729E2C1B9A54F1004A00EB /* Resources */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t\t51729E301B9A54F1004A00EB /* PBXTargetDependency */,\n\t\t\t);\n\t\t\tname = ExampleUITests;\n\t\t\tproductName = ExampleUITests;\n\t\t\tproductReference = 51729E2E1B9A54F1004A00EB /* ExampleUITests.xctest */;\n\t\t\tproductType = \"com.apple.product-type.bundle.ui-testing\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t51729E121B9A54F1004A00EB /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 1400;\n\t\t\t\tORGANIZATIONNAME = Xmartlabs;\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t51729E191B9A54F1004A00EB = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tProvisioningStyle = Automatic;\n\t\t\t\t\t};\n\t\t\t\t\t51729E2D1B9A54F1004A00EB = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.0;\n\t\t\t\t\t\tLastSwiftMigration = 1020;\n\t\t\t\t\t\tTestTargetID = 51729E191B9A54F1004A00EB;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 51729E151B9A54F1004A00EB /* Build configuration list for PBXProject \"Example\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = en;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 51729E111B9A54F1004A00EB;\n\t\t\tproductRefGroup = 51729E1B1B9A54F1004A00EB /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectReferences = (\n\t\t\t\t{\n\t\t\t\t\tProductGroup = 51729E421B9A5841004A00EB /* Products */;\n\t\t\t\t\tProjectRef = 51729E411B9A5841004A00EB /* Eureka.xcodeproj */;\n\t\t\t\t},\n\t\t\t);\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t51729E191B9A54F1004A00EB /* Example */,\n\t\t\t\t51729E2D1B9A54F1004A00EB /* ExampleUITests */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXReferenceProxy section */\n\t\t51729E471B9A5841004A00EB /* Eureka.framework */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.framework;\n\t\t\tpath = Eureka.framework;\n\t\t\tremoteRef = 51729E461B9A5841004A00EB /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n\t\t51729E491B9A5841004A00EB /* EurekaTests.xctest */ = {\n\t\t\tisa = PBXReferenceProxy;\n\t\t\tfileType = wrapper.cfbundle;\n\t\t\tpath = EurekaTests.xctest;\n\t\t\tremoteRef = 51729E481B9A5841004A00EB /* PBXContainerItemProxy */;\n\t\t\tsourceTree = BUILT_PRODUCTS_DIR;\n\t\t};\n/* End PBXReferenceProxy section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t51729E181B9A54F1004A00EB /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t51729E281B9A54F1004A00EB /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t284D28B81E4917A000BB38E7 /* SwitchCell.xib in Resources */,\n\t\t\t\t284D28BA1E491FEF00BB38E7 /* TextCell.xib in Resources */,\n\t\t\t\t51729E251B9A54F1004A00EB /* Assets.xcassets in Resources */,\n\t\t\t\t51729E711B9A660A004A00EB /* WeekDaysCell.xib in Resources */,\n\t\t\t\t284D28B61E49121E00BB38E7 /* DatePickerCell.xib in Resources */,\n\t\t\t\t28CD97C21BB32F0E00AFDA67 /* EurekaSectionHeader.xib in Resources */,\n\t\t\t\t51729E231B9A54F1004A00EB /* Main.storyboard in Resources */,\n\t\t\t\tD4ACF9132074B52200AEA952 /* EmojiCell.xib in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729E2C1B9A54F1004A00EB /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t51729E161B9A54F1004A00EB /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t8F32506B205AAF66006AF0A6 /* PlainTableViewExample.swift in Sources */,\n\t\t\t\t8F325069205AAF1E006AF0A6 /* SwipeActionsController.swift in Sources */,\n\t\t\t\t51729E201B9A54F1004A00EB /* ViewController.swift in Sources */,\n\t\t\t\t8F32505D205AAC68006AF0A6 /* FormatterExample.swift in Sources */,\n\t\t\t\t51729E6E1B9A6601004A00EB /* CustomCells.swift in Sources */,\n\t\t\t\t8F32505B205AAC2A006AF0A6 /* DisabledRowsExample.swift in Sources */,\n\t\t\t\t8F325057205AABDB006AF0A6 /* NativeEventExample.swift in Sources */,\n\t\t\t\t287A14401D99A96100FFE6EB /* ImageRow.swift in Sources */,\n\t\t\t\t287A143F1D99A96100FFE6EB /* ImagePickerController.swift in Sources */,\n\t\t\t\t8F325055205AABA6006AF0A6 /* NavigationAccessoryController.swift in Sources */,\n\t\t\t\t8F325065205AAD23006AF0A6 /* CustomDesignController.swift in Sources */,\n\t\t\t\t8F32504F205AAA93006AF0A6 /* RowsExample.swift in Sources */,\n\t\t\t\t8F32505F205AAC8E006AF0A6 /* InlineRowsExample.swift in Sources */,\n\t\t\t\t51729E1E1B9A54F1004A00EB /* AppDelegate.swift in Sources */,\n\t\t\t\t2837E2A01BA3A5A800A1952C /* FloatLabelTextField.swift in Sources */,\n\t\t\t\t8F325063205AACF4006AF0A6 /* ValidationsController.swift in Sources */,\n\t\t\t\t8F325059205AAC06006AF0A6 /* HiddenRowsExample.swift in Sources */,\n\t\t\t\t8F325053205AAB6F006AF0A6 /* FieldRowCustomizationController.swift in Sources */,\n\t\t\t\t8F325051205AAB35006AF0A6 /* CustomCellsViewController.swift in Sources */,\n\t\t\t\t8F325067205AAD7A006AF0A6 /* MultivaluedExamples.swift in Sources */,\n\t\t\t\t8F325061205AACB9006AF0A6 /* ListSectionsController.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n\t\t51729E2A1B9A54F1004A00EB /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t28E8554C1B9EA46F004E5189 /* FieldRowUITests.swift in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXTargetDependency section */\n\t\t28C777271BA14A52000ED936 /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tname = Eureka;\n\t\t\ttargetProxy = 28C777261BA14A52000ED936 /* PBXContainerItemProxy */;\n\t\t};\n\t\t51729E301B9A54F1004A00EB /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\ttarget = 51729E191B9A54F1004A00EB /* Example */;\n\t\t\ttargetProxy = 51729E2F1B9A54F1004A00EB /* PBXContainerItemProxy */;\n\t\t};\n\t\tBF4298991BA0997D001D107B /* PBXTargetDependency */ = {\n\t\t\tisa = PBXTargetDependency;\n\t\t\tname = Eureka;\n\t\t\ttargetProxy = BF4298981BA0997D001D107B /* PBXContainerItemProxy */;\n\t\t};\n/* End PBXTargetDependency section */\n\n/* Begin PBXVariantGroup section */\n\t\t28CD97C01BB32F0E00AFDA67 /* EurekaSectionHeader.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t28CD97C11BB32F0E00AFDA67 /* Base */,\n\t\t\t);\n\t\t\tname = EurekaSectionHeader.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E211B9A54F1004A00EB /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E221B9A54F1004A00EB /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tpath = Example;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E261B9A54F1004A00EB /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E271B9A54F1004A00EB /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tpath = Example;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t51729E6F1B9A660A004A00EB /* WeekDaysCell.xib */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t51729E701B9A660A004A00EB /* Base */,\n\t\t\t);\n\t\t\tname = WeekDaysCell.xib;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t51729E351B9A54F1004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Onone\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729E361B9A54F1004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t51729E381B9A54F1004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Example/Example/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.Example;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE = \"\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729E391B9A54F1004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCODE_SIGN_IDENTITY = \"iPhone Developer\";\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCODE_SIGN_STYLE = Automatic;\n\t\t\t\tDEVELOPMENT_TEAM = \"\";\n\t\t\t\tINFOPLIST_FILE = Example/Example/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 11.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.Example;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tPROVISIONING_PROFILE_SPECIFIER = \"\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t51729E3B1B9A54F1004A00EB /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = Example/UITests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.ExampleUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_TARGET_NAME = Example;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t51729E3C1B9A54F1004A00EB /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbuildSettings = {\n\t\t\t\tINFOPLIST_FILE = Example/UITests/Info.plist;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 9.0;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks @loader_path/Frameworks\";\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.xmartlabs.ExampleUITests;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tSWIFT_OPTIMIZATION_LEVEL = \"-Owholemodule\";\n\t\t\t\tSWIFT_VERSION = 5.0;\n\t\t\t\tTEST_TARGET_NAME = Example;\n\t\t\t\tUSES_XCTRUNNER = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t51729E151B9A54F1004A00EB /* Build configuration list for PBXProject \"Example\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729E351B9A54F1004A00EB /* Debug */,\n\t\t\t\t51729E361B9A54F1004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t51729E371B9A54F1004A00EB /* Build configuration list for PBXNativeTarget \"Example\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729E381B9A54F1004A00EB /* Debug */,\n\t\t\t\t51729E391B9A54F1004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t51729E3A1B9A54F1004A00EB /* Build configuration list for PBXNativeTarget \"ExampleUITests\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t51729E3B1B9A54F1004A00EB /* Debug */,\n\t\t\t\t51729E3C1B9A54F1004A00EB /* Release */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 51729E121B9A54F1004A00EB /* Project object */;\n}\n"
  },
  {
    "path": "Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:Example.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>IDEDidComputeMac32BitWarning</key>\n\t<true/>\n</dict>\n</plist>\n"
  },
  {
    "path": "Example.xcodeproj/xcshareddata/xcschemes/Example.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1400\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"51729E191B9A54F1004A00EB\"\n               BuildableName = \"Example.app\"\n               BlueprintName = \"Example\"\n               ReferencedContainer = \"container:Example.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729E191B9A54F1004A00EB\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <Testables>\n         <TestableReference\n            skipped = \"NO\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"51729E2D1B9A54F1004A00EB\"\n               BuildableName = \"ExampleUITests.xctest\"\n               BlueprintName = \"ExampleUITests\"\n               ReferencedContainer = \"container:Example.xcodeproj\">\n            </BuildableReference>\n         </TestableReference>\n      </Testables>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729E191B9A54F1004A00EB\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Release\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"51729E191B9A54F1004A00EB\"\n            BuildableName = \"Example.app\"\n            BlueprintName = \"Example\"\n            ReferencedContainer = \"container:Example.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2019 XMARTLABS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "Package.swift",
    "content": "// swift-tools-version:5.0\nimport PackageDescription\n\nlet package = Package(\n    name: \"Eureka\",\n    platforms: [.iOS(.v9)],\n    products: [\n        .library(name: \"Eureka\", targets: [\"Eureka\"])\n    ],\n    targets: [\n        .target(\n            name: \"Eureka\",\n            path: \"Source\"\n        ),\n        .testTarget(\n            name: \"EurekaTests\",\n            dependencies: [\"Eureka\"],\n            path: \"Tests\"\n        )\n    ]\n)\n"
  },
  {
    "path": "README.md",
    "content": "![Eureka: Elegant form builder in Swift](Eureka.png)\n\n<p align=\"center\">\n<a href=\"https://travis-ci.org/xmartlabs/Eureka\"><img src=\"https://travis-ci.org/xmartlabs/Eureka.svg?branch=master\" alt=\"Build status\" /></a>\n<img src=\"https://img.shields.io/badge/platform-iOS-blue.svg?style=flat\" alt=\"Platform iOS\" />\n<a href=\"https://developer.apple.com/swift\"><img src=\"https://img.shields.io/badge/swift5-compatible-4BC51D.svg?style=flat\" alt=\"Swift 5 compatible\" /></a>\n<a href=\"https://github.com/Carthage/Carthage\"><img src=\"https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat\" alt=\"Carthage compatible\" /></a>\n<a href=\"https://cocoapods.org/pods/Eureka\"><img src=\"https://img.shields.io/cocoapods/v/Eureka.svg\" alt=\"CocoaPods compatible\" /></a>\n<a href=\"https://raw.githubusercontent.com/xmartlabs/Eureka/master/LICENSE\"><img src=\"http://img.shields.io/badge/license-MIT-blue.svg?style=flat\" alt=\"License: MIT\" /></a>\n<a href=\"https://codebeat.co/projects/github-com-xmartlabs-eureka\"><img alt=\"codebeat badge\" src=\"https://codebeat.co/badges/16f29afb-f072-4633-9497-333c6eb71263\" /></a>\n</p>\n\nMade with ❤️ by [XMARTLABS](http://xmartlabs.com). This is the re-creation of [XLForm] in Swift.\n\n[简体中文](Documentation/README_CN.md)\n\n## Overview\n\n<table>\n  <tr>\n    <th>\n      <img src=\"Example/Media/EurekaExample1.gif\" width=\"220\"/>\n    </th>\n    <th>\n      <img src=\"Example/Media/EurekaExample2.gif\" width=\"220\"/>\n    </th>\n    <th>\n    <img src=\"Example/Media/EurekaExample3.gif\" width=\"220\"/>\n    </th>\n  </tr>\n</table>\n\n## Contents\n\n* [Requirements]\n* [Usage]\n  + [How to create a Form]\n  + [Getting row values]\n  + [Operators]\n  + [Using the callbacks]\n  + [Section Header and Footer]\n  + [Dynamically hide and show rows (or sections)]\n  + [List sections]\n  + [Multivalued sections]\n  + [Validations]\n  + [Swipe Actions]\n* [Custom rows]\n  + [Basic custom rows]\n  + [Custom inline rows]\n  + [Custom presenter rows]\n* [Row catalog]\n* [Installation]\n* [FAQ]\n\n**For more information look at [our blog post] that introduces *Eureka*.**\n\n## Requirements (for latest release)\n\n* Xcode 11+\n* Swift 5.0+\n\n### Example project\n\nYou can clone and run the Example project to see examples of most of Eureka's features.\n\n<table>\n  <tr>\n    <th>\n      <img src=\"Example/Media/EurekaNavigation.gif\" width=\"200\"/>\n    </th>\n    <th>\n      <img src=\"Example/Media/EurekaRows.gif\" width=\"200\"/>\n    </th>\n  </tr>\n</table>\n\n## Usage\n\n### How to create a form\nBy extending `FormViewController` you can then simply add sections and rows to the `form` variable.\n\n```swift\nimport Eureka\n\nclass MyFormViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form +++ Section(\"Section1\")\n            <<< TextRow(){ row in\n                row.title = \"Text Row\"\n                row.placeholder = \"Enter text here\"\n            }\n            <<< PhoneRow(){\n                $0.title = \"Phone Row\"\n                $0.placeholder = \"And numbers here\"\n            }\n        +++ Section(\"Section2\")\n            <<< DateRow(){\n                $0.title = \"Date Row\"\n                $0.value = Date(timeIntervalSinceReferenceDate: 0)\n            }\n    }\n}\n```\n\nIn the example we create two sections with standard rows, the result is this:\n\n<center>\n<img src=\"Example/Media/EurekaHowTo.gif\" width=\"200\" alt=\"Screenshot of Custom Cells\"/>\n</center>\n\nYou could create a form by just setting up the `form` property by yourself without extending from `FormViewController` but this method is typically more convenient.\n\n#### Configuring the keyboard navigation accesory\n\nTo change the behaviour of this you should set the navigation options of your controller. The `FormViewController` has a `navigationOptions` variable which is an enum and can have one or more of the following values:\n\n- **disabled**: no view at all\n- **enabled**: enable view at the bottom\n- **stopDisabledRow**: if the navigation should stop when the next row is disabled\n- **skipCanNotBecomeFirstResponderRow**: if the navigation should skip the rows that return false to `canBecomeFirstResponder()`\n\nThe default value is `enabled & skipCanNotBecomeFirstResponderRow`\n\nTo enable smooth scrolling to off-screen rows, enable it via the `animateScroll` property. By default, the `FormViewController` jumps immediately between rows when the user hits the next or previous buttons in the keyboard navigation accesory, including when the next row is off screen.\n\nTo set the amount of space between the keyboard and the highlighted row following a navigation event, set the `rowKeyboardSpacing` property. By default, when the form scrolls to an offscreen view no space will be left between the top of the keyboard and the bottom of the row.\n\n```swift\nclass MyFormViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        form = ...\n\n\t// Enables the navigation accessory and stops navigation when a disabled row is encountered\n\tnavigationOptions = RowNavigationOptions.Enabled.union(.StopDisabledRow)\n\t// Enables smooth scrolling on navigation to off-screen rows\n\tanimateScroll = true\n\t// Leaves 20pt of space between the keyboard and the highlighted row after scrolling to an off screen row\n\trowKeyboardSpacing = 20\n    }\n}\n```\n\nIf you want to change the whole navigation accessory view, you will have to override the `navigationAccessoryView` variable in your subclass of `FormViewController`.\n\n\n### Getting row values\n\nThe `Row` object holds a  ***value*** of a specific type.\nFor example, a `SwitchRow` holds a `Bool` value, while a `TextRow` holds a `String` value.\n\n```swift\n// Get the value of a single row\nlet row: TextRow? = form.rowBy(tag: \"MyRowTag\")\nlet value = row.value\n\n// Get the value of all rows which have a Tag assigned\n// The dictionary contains the 'rowTag':value pairs.\nlet valuesDictionary = form.values()\n```\n\n### Operators\n\nEureka includes custom operators to make form creation easy:\n\n#### +++ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Add a section\n```swift\nform +++ Section()\n\n// Chain it to add multiple Sections\nform +++ Section(\"First Section\") +++ Section(\"Another Section\")\n\n// Or use it with rows and get a blank section for free\nform +++ TextRow()\n     +++ TextRow()  // Each row will be on a separate section\n```\n\n#### <<< &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Insert a row\n\n```swift\nform +++ Section()\n        <<< TextRow()\n        <<< DateRow()\n\n// Or implicitly create the Section\nform +++ TextRow()\n        <<< DateRow()\n```\n\n#### += &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Append an array\n\n```swift\n// Append Sections into a Form\nform += [Section(\"A\"), Section(\"B\"), Section(\"C\")]\n\n// Append Rows into a Section\nsection += [TextRow(), DateRow()]\n```\n\n### Result builders\n\nEureka includes result builders to make form creation easy:\n\n#### @SectionBuilder\n```swift\n// Section + Section\nform = (Section(\"A\") +++ {\n    URLRow(\"UrlRow_f1\") { $0.title = \"Url\" }\n    if something {\n        TwitterRow(\"TwitterRow_f2\") { $0.title = \"Twitter\" }\n    } else {\n        TwitterRow(\"TwitterRow_f1\") { $0.title = \"Twitter\" }\n    }\n    AccountRow(\"AccountRow_f1\") { $0.title = \"Account\" }\n})\n\n// Form + Section\nform +++ {\n    if something {\n        PhoneRow(\"PhoneRow_f1\") { $0.title = \"Phone\" }\n    } else {\n        PhoneRow(\"PhoneRow_f2\") { $0.title = \"Phone\" }\n    }\n    PasswordRow(\"PasswordRow_f1\") { $0.title = \"Password\" }\n}\n```\n\n#### @FormBuilder\n```swift\n@FormBuilder\nvar form: Form {\n    Section(\"Section A\") { section in\n        section.tag = \"Section_A\"\n    }\n    if true {\n        Section(\"Section B\") { section in\n            section.tag = \"Section_B\"\n        }\n    }\n    NameRow(\"NameRow_f1\") { $0.title = \"Name\" }\n}\n```\n\n### Using the callbacks\n\nEureka includes callbacks to change the appearance and behavior of a row.\n\n#### Understanding Row and Cell\n\nA `Row` is an abstraction Eureka uses which holds a **value** and contains the view `Cell`. The `Cell` manages the view and subclasses `UITableViewCell`.\n\nHere is an example:\n\n```swift\nlet row  = SwitchRow(\"SwitchRow\") { row in      // initializer\n                        row.title = \"The title\"\n                    }.onChange { row in\n                        row.title = (row.value ?? false) ? \"The title expands when on\" : \"The title\"\n                        row.updateCell()\n                    }.cellSetup { cell, row in\n                        cell.backgroundColor = .lightGray\n                    }.cellUpdate { cell, row in\n                        cell.textLabel?.font = .italicSystemFont(ofSize: 18.0)\n                }\n```\n\n<img src=\"Example/Media/EurekaOnChange.gif\" width=\"300\" alt=\"Screenshot of Disabled Row\"/>\n\n#### Callbacks list\n\n* **onChange()**\n\n\tCalled when the value of a row changes. You might be interested in adjusting some parameters here or even make some other rows appear or disappear.\n\n* **onCellSelection()**\n\n\tCalled each time the user taps on the row and it gets selected. Note that this will also get called for disabled rows so you should start your code inside this callback with something like `guard !row.isDisabled else { return }`\n\n* **cellSetup()**\n\n\tCalled only once when the cell is first configured. Set permanent settings here.\n\n* **cellUpdate()**\n\n\tCalled each time the cell appears on screen. You can change the appearance here using variables that may not be present on cellSetup().\n\n* **onCellHighlightChanged()**\n\n  Called whenever the cell or any subview become or resign the first responder.\n\n* **onRowValidationChanged()**\n\n    Called whenever the the validation errors associated with a row changes.\n\n* **onExpandInlineRow()**\n\n  Called before expanding the inline row. Applies to rows conforming `InlineRowType` protocol.\n\n* **onCollapseInlineRow()**\n\n  Called before collapsing the inline row. Applies to rows conforming `InlineRowType` protocol.\n\n* **onPresent()**\n\n\tCalled by a row just before presenting another view controller. Applies to rows conforming `PresenterRowType` protocol. Use it to set up the presented controller.\n\n\n### Section Header and Footer\n\nYou can set a title `String` or a custom `View` as the header or footer of a `Section`.\n\n#### String title\n```swift\nSection(\"Title\")\n\nSection(header: \"Title\", footer: \"Footer Title\")\n\nSection(footer: \"Footer Title\")\n```\n\n#### Custom view\nYou can use a Custom View from a `.xib` file:\n\n```swift\nSection() { section in\n    var header = HeaderFooterView<MyHeaderNibFile>(.nibFile(name: \"MyHeaderNibFile\", bundle: nil))\n\n    // Will be called every time the header appears on screen\n    header.onSetupView = { view, _ in\n        // Commonly used to setup texts inside the view\n        // Don't change the view hierarchy or size here!\n    }\n    section.header = header\n}\n```\n\nOr a custom `UIView` created programmatically\n\n```swift\nSection(){ section in\n    var header = HeaderFooterView<MyCustomUIView>(.class)\n    header.height = {100}\n    header.onSetupView = { view, _ in\n        view.backgroundColor = .red\n    }\n    section.header = header\n}\n```\nOr just build the view with a Callback\n```swift\nSection(){ section in\n    section.header = {\n          var header = HeaderFooterView<UIView>(.callback({\n              let view = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))\n              view.backgroundColor = .red\n              return view\n          }))\n          header.height = { 100 }\n          return header\n        }()\n}\n```\n\n### Dynamically hide and show rows (or sections)  <a name=\"hide-show-rows\"></a>\n\n<img src=\"Example/Media/EurekaSwitchSections.gif\" width=\"300\" alt=\"Screenshot of Hidden Rows\" />\n\nIn this case we are hiding and showing whole sections.\n\nTo accomplish this each row has a `hidden` variable of optional type `Condition` which can be set using a function or `NSPredicate`.\n\n\n#### Hiding using a function condition\n\nUsing the `function` case of `Condition`:\n```swift\nCondition.function([String], (Form)->Bool)\n```\nThe array of `String` to pass should contain the tags of the rows this row depends on. Each time the value of any of those rows changes the function is reevaluated.\nThe function then takes the `Form` and returns a `Bool` indicating whether the row should be hidden or not. This the most powerful way of setting up the `hidden` property as it has no explicit limitations of what can be done.\n\n```swift\nform +++ Section()\n            <<< SwitchRow(\"switchRowTag\"){\n                $0.title = \"Show message\"\n            }\n            <<< LabelRow(){\n\n                $0.hidden = Condition.function([\"switchRowTag\"], { form in\n                    return !((form.rowBy(tag: \"switchRowTag\") as? SwitchRow)?.value ?? false)\n                })\n                $0.title = \"Switch is on!\"\n        }\n```\n\n<img src=\"Example/Media/EurekaHidden.gif\" width=\"300\" alt=\"Screenshot of Hidden Rows\" />\n\n```swift\npublic enum Condition {\n    case function([String], (Form)->Bool)\n    case predicate(NSPredicate)\n}\n```\n\n#### Hiding using an NSPredicate\n\nThe `hidden` variable can also be set with a NSPredicate. In the predicate string you can reference values of other rows by their tags to determine if a row should be hidden or visible.\nThis will only work if the values of the rows the predicate has to check are NSObjects (String and Int will work as they are bridged to their ObjC counterparts, but enums won't work).\nWhy could it then be useful to use predicates when they are more limited? Well, they can be much simpler, shorter and readable than functions. Look at this example:\n\n```swift\n$0.hidden = Condition.predicate(NSPredicate(format: \"$switchTag == false\"))\n```\n\nAnd we can write it even shorter since `Condition` conforms to `ExpressibleByStringLiteral`:\n\n```swift\n$0.hidden = \"$switchTag == false\"\n```\n\n*Note: we will substitute the value of the row whose tag is 'switchTag' instead of '$switchTag'*\n\nFor all of this to work, **all of the implicated rows must have a tag** as the tag will identify them.\n\nWe can also hide a row by doing:\n```swift\n$0.hidden = true\n```\nas `Condition` conforms to `ExpressibleByBooleanLiteral`.\n\nNot setting the `hidden` variable will leave the row always visible.\n\nIf you manually set the hidden (or disabled) condition after the form has been displayed you may have to call `row.evaluateHidden()` to force Eureka to reevaluate the new condition.\nSee [this FAQ section](https://github.com/xmartlabs/Eureka#row-does-not-update-after-changing-hidden-or-disabled-condition) for more info.\n\n##### Sections\nFor sections this works just the same. That means we can set up section `hidden` property to show/hide it dynamically.\n\n##### Disabling rows\nTo disable rows, each row has an `disabled` variable which is also an optional `Condition` type property. This variable also works the same as the `hidden` variable so that it requires the rows to have a tag.\n\nNote that if you want to disable a row permanently you can also set `disabled` variable to `true`.\n\n### List Sections\n\nTo display a list of options, Eureka includes a special section called `SelectableSection`.\nWhen creating one you need to pass the type of row to use in the options and the `selectionType`.\nThe `selectionType` is an enum which can be either `multipleSelection` or `singleSelection(enableDeselection: Bool)` where the `enableDeselection` parameter determines if the selected rows can be deselected or not.\n\n```swift\nform +++ SelectableSection<ListCheckRow<String>>(\"Where do you live\", selectionType: .singleSelection(enableDeselection: true))\n\nlet continents = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\nfor option in continents {\n    form.last! <<< ListCheckRow<String>(option){ listRow in\n        listRow.title = option\n        listRow.selectableValue = option\n        listRow.value = nil\n    }\n}\n```\n\n##### What kind of rows can be used?\n\nTo create such a section you have to create a row that conforms the `SelectableRowType` protocol.\n\n```swift\npublic protocol SelectableRowType : RowType {\n    var selectableValue : Value? { get set }\n}\n```\n\nThis `selectableValue` is where the value of the row will be permanently stored. The `value` variable will be used to determine if the row is selected or not, being 'selectableValue' if selected or nil otherwise.\nEureka includes the `ListCheckRow` which is used for example. In the custom rows of the Examples project you can also find the `ImageCheckRow`.\n\n##### Getting the selected rows\n\nTo easily get the selected row/s of a `SelectableSection` there are two methods: `selectedRow()` and `selectedRows()` which can be called to get the selected row in case it is a `SingleSelection` section or all the selected rows if it is a `MultipleSelection` section.\n\n##### Grouping options in sections\n\nAdditionally you can setup list of options to be grouped by sections using following properties of `SelectorViewController`:\n\n- `sectionKeyForValue` - a closure that should return key for particular row value. This key is later used to break options by sections.\n\n- `sectionHeaderTitleForKey` - a closure that returns header title for a section for particular key. By default returns the key itself.\n\n- `sectionFooterTitleForKey` - a closure that returns footer title for a section for particular key.\n\n### Multivalued Sections\n\nEureka supports multiple values for a certain field (such as telephone numbers in a contact) by using Multivalued sections. It allows us to easily create insertable, deletable and reorderable sections.\n\n<img src=\"Example/Media/EurekaMultivalued.gif\" width=\"300\" alt=\"Screenshot of Multivalued Section\" />\n\n#### How to create a multivalued section\n\nIn order to create a multivalued section we have to use `MultivaluedSection` type instead of the regular `Section` type. `MultivaluedSection` extends `Section` and has some additional properties to configure multivalued section behavior.\n\nlet's dive into a code example...\n\n```swift\nform +++\n    MultivaluedSection(multivaluedOptions: [.Reorder, .Insert, .Delete],\n                       header: \"Multivalued TextField\",\n                       footer: \".Insert adds a 'Add Item' (Add New Tag) button row as last cell.\") {\n        $0.addButtonProvider = { section in\n            return ButtonRow(){\n                $0.title = \"Add New Tag\"\n            }\n        }\n        $0.multivaluedRowToInsertAt = { index in\n            return NameRow() {\n                $0.placeholder = \"Tag Name\"\n            }\n        }\n        $0 <<< NameRow() {\n            $0.placeholder = \"Tag Name\"\n        }\n    }\n```\n\nPrevious code snippet shows how to create a multivalued section. In this case we want to insert, delete and reorder rows as multivaluedOptions argument indicates.\n\n`addButtonProvider` allows us to customize the button row which inserts a new row when tapped and `multivaluedOptions` contains `.Insert` value.\n\n`multivaluedRowToInsertAt` closure property is called by Eureka each time a new row needs to be inserted. In order to provide the row to add into multivalued section we should set this property. Eureka passes the index as closure parameter. Notice that we can return any kind of row, even custom rows, even though in most cases multivalued section rows are of the same type.\n\nEureka automatically adds a button row when we create a insertable multivalued section. We can customize how the this button row looks like as we explained before. `showInsertIconInAddButton` property indicates if plus button (insert style) should appear in the left of the button, true by default.\n\nThere are some considerations we need to have in mind when creating insertable sections. Any row added to the insertable multivalued section should be placed above the row that Eureka automatically adds to insert new rows. This can be easily achieved by adding these additional rows to the section from inside the section's initializer closure (last parameter of section initializer) so then Eureka adds the adds insert button at the end of the section.\n\n#### Editing mode\n\nBy default Eureka will set the tableView's `isEditing` to true only if there is a MultivaluedSection in the form. This will be done in `viewWillAppear` the first time a form is presented.\n\nFor more information on how to use multivalued sections please take a look at Eureka example project which contains several usage examples.\n\n#### Custom add button\nIf you want to use an add button which is not a `ButtonRow` then you can use `GenericMultivaluedSection<AddButtonType>`, where `AddButtonType` is the type of the row you want to use as add button. This is useful if you want to use a custom row to change the UI of the button.\n\nExample:\n\n```swift\nGenericMultivaluedSection<LabelRow>(multivaluedOptions: [.Reorder, .Insert, .Delete], {\n    $0.addButtonProvider = { section in\n        return LabelRow(){\n            $0.title = \"A Label row as add button\"\n        }\n    }\n    // ...\n}\n```\n\n### Validations\n\nEureka 2.0.0 introduces the much requested built-in validations feature.\n\nA row has a collection of `Rules` and a specific configuration that determines when validation rules should be evaluated.\n\nThere are some rules provided by default, but you can also create new ones on your own.\n\nThe provided rules are:\n* RuleRequired\n* RuleEmail\n* RuleURL\n* RuleGreaterThan, RuleGreaterOrEqualThan, RuleSmallerThan, RuleSmallerOrEqualThan\n* RuleMinLength, RuleMaxLength\n* RuleClosure\n\nLet's see how to set up the validation rules.\n\n```swift\n\noverride func viewDidLoad() {\n        super.viewDidLoad()\n        form\n          +++ Section(header: \"Required Rule\", footer: \"Options: Validates on change\")\n\n            <<< TextRow() {\n                $0.title = \"Required Rule\"\n                $0.add(rule: RuleRequired())\n\n\t\t// This could also have been achieved using a closure that returns nil if valid, or a ValidationError otherwise.\n\t\t/*\n\t\tlet ruleRequiredViaClosure = RuleClosure<String> { rowValue in\n\t\treturn (rowValue == nil || rowValue!.isEmpty) ? ValidationError(msg: \"Field required!\") : nil\n\t\t}\n\t\t$0.add(rule: ruleRequiredViaClosure)\n\t\t*/\n\n                $0.validationOptions = .validatesOnChange\n            }\n            .cellUpdate { cell, row in\n                if !row.isValid {\n                    cell.titleLabel?.textColor = .systemRed\n                }\n            }\n\n          +++ Section(header: \"Email Rule, Required Rule\", footer: \"Options: Validates on change after blurred\")\n\n            <<< TextRow() {\n                $0.title = \"Email Rule\"\n                $0.add(rule: RuleRequired())\n                $0.add(rule: RuleEmail())\n                $0.validationOptions = .validatesOnChangeAfterBlurred\n            }\n            .cellUpdate { cell, row in\n                if !row.isValid {\n                    cell.titleLabel?.textColor = .systemRed\n                }\n            }\n\n```\n\nAs you can see in the previous code snippet we can set up as many rules as we want in a row by invoking row's `add(rule:)` function.\n\nRow also provides  `func remove(ruleWithIdentifier identifier: String)` to remove a rule. In order to use it we must assign an id to the rule after creating it.\n\nSometimes the collection of rules we want to use on a row is the same we want to use on many other rows. In this case we can set up all validation rules using a `RuleSet` which is a collection of validation rules.\n\n```swift\nvar rules = RuleSet<String>()\nrules.add(rule: RuleRequired())\nrules.add(rule: RuleEmail())\n\nlet row = TextRow() {\n            $0.title = \"Email Rule\"\n            $0.add(ruleSet: rules)\n            $0.validationOptions = .validatesOnChangeAfterBlurred\n        }\n```\n\nEureka allows us to specify when validation rules should be evaluated. We can do it by setting up `validationOptions` row's property, which can have the following values:\n\n\n* `.validatesOnChange` - Validates whenever a row value changes.\n* `.validatesOnBlur` - (Default value) validates right after the cell resigns first responder. Not applicable for all rows.\n* `.validatesOnChangeAfterBlurred` - Validates whenever the row value changes after it resigns first responder for the first time.\n* `.validatesOnDemand` - We should manually validate the row or form by invoking `validate()` method.\n\nIf you want to validate the entire form (all the rows) you can manually invoke Form `validate()` method.\n\n#### How to get validation errors\n\nEach row has the `validationErrors` property that can be used to retrieve all validation errors. This property just holds the validation error list of the latest row validation execution, which means it doesn't evaluate the validation rules of the row.\n\n#### Note on types\n\nAs expected, the Rules must use the same types as the Row object. Be extra careful to check the row type used. You might see a compiler error (\"Incorrect arugment label in call (have 'rule:' expected 'ruleSet:')\" that is not pointing to the problem when mixing types.\n\n### Swipe Actions\n\nBy using swipe actions we can define multiple `leadingSwipe` and `trailingSwipe` actions per row. As swipe actions depend on iOS system features, `leadingSwipe` is available on iOS 11.0+ only.\n\nLet's see how to define swipe actions.\n\n```swift\nlet row = TextRow() {\n            let deleteAction = SwipeAction(\n                style: .destructive,\n                title: \"Delete\",\n                handler: { (action, row, completionHandler) in\n                    //add your code here.\n                    //make sure you call the completionHandler once done.\n                    completionHandler?(true)\n                })\n            deleteAction.image = UIImage(named: \"icon-trash\")\n\n            $0.trailingSwipe.actions = [deleteAction]\n            $0.trailingSwipe.performsFirstActionWithFullSwipe = true\n\n            //please be aware: `leadingSwipe` is only available on iOS 11+ only\n            let infoAction = SwipeAction(\n                style: .normal,\n                title: \"Info\",\n                handler: { (action, row, completionHandler) in\n                    //add your code here.\n                    //make sure you call the completionHandler once done.\n                    completionHandler?(true)\n                })\n            infoAction.actionBackgroundColor = .blue\n            infoAction.image = UIImage(named: \"icon-info\")\n\n            $0.leadingSwipe.actions = [infoAction]\n            $0.leadingSwipe.performsFirstActionWithFullSwipe = true\n        }\n```\n\nSwipe Actions need `tableView.isEditing` be set to `false`. Eureka will set this to `true` if there is a MultivaluedSection in the form (in the `viewWillAppear`).\nIf you have both MultivaluedSections and swipe actions in the same form you should set `isEditing` according to your needs.\n\n## Custom rows\n\nIt is very common that you need a row that is different from those included in Eureka. If this is the case you will have to create your own row but this should not be difficult. You can read [this tutorial on how to create custom rows](https://blog.xmartlabs.com/2016/09/06/Eureka-custom-row-tutorial/) to get started. You might also want to have a look at [EurekaCommunity] which includes some extra rows ready to be added to Eureka.\n\n### Basic custom rows\n\nTo create a row with custom behaviour and appearance you'll probably want to create subclasses of `Row` and `Cell`.\n\nRemember that `Row` is the abstraction Eureka uses, while the `Cell` is the actual `UITableViewCell` in charge of the view.\nAs the `Row` contains the `Cell`, both `Row` and `Cell` must be defined for the same **value** type.\n\n```swift\n// Custom Cell with value type: Bool\n// The cell is defined using a .xib, so we can set outlets :)\npublic class CustomCell: Cell<Bool>, CellType {\n    @IBOutlet weak var switchControl: UISwitch!\n    @IBOutlet weak var label: UILabel!\n\n    public override func setup() {\n        super.setup()\n        switchControl.addTarget(self, action: #selector(CustomCell.switchValueChanged), for: .valueChanged)\n    }\n\n    func switchValueChanged(){\n        row.value = switchControl.on\n        row.updateCell() // Re-draws the cell which calls 'update' bellow\n    }\n\n    public override func update() {\n        super.update()\n        backgroundColor = (row.value ?? false) ? .white : .black\n    }\n}\n\n// The custom Row also has the cell: CustomCell and its correspond value\npublic final class CustomRow: Row<CustomCell>, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        // We set the cellProvider to load the .xib corresponding to our cell\n        cellProvider = CellProvider<CustomCell>(nibName: \"CustomCell\")\n    }\n}\n```\nThe result: <br>\n<img src=\"Example/Media/EurekaCustomRow.gif\" alt=\"Screenshot of Disabled Row\"/>\n\n<br>\nCustom rows need to subclass `Row<CellType>` and conform to `RowType` protocol.\nCustom cells need to subclass `Cell<ValueType>` and conform to `CellType` protocol.\n\nJust like the callbacks cellSetup and CellUpdate, the `Cell` has the setup and update methods where you can customize it.\n\n\n### Custom inline rows\n\nAn inline row is a specific type of row that shows dynamically a row below it, normally an inline row changes between an expanded and collapsed mode whenever the row is tapped.\n\nSo to create an inline row we need 2 rows, the row that is \"always\" visible and the row that will expand/collapse.\n\nAnother requirement is that the value type of these 2 rows must be the same. This means if one row holds a `String` value then the other must have a `String` value too.\n\nOnce we have these 2 rows, we should make the top row type conform to `InlineRowType`.\nThis protocol requires you to define an `InlineRow` typealias and a `setupInlineRow` function.\nThe `InlineRow` type will be the type of the row that will expand/collapse.\nTake this as an example:\n\n```swift\nclass PickerInlineRow<T> : Row<PickerInlineCell<T>> where T: Equatable {\n\n    public typealias InlineRow = PickerRow<T>\n    open var options = [T]()\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    public func setupInlineRow(_ inlineRow: InlineRow) {\n        inlineRow.options = self.options\n        inlineRow.displayValueFor = self.displayValueFor\n        inlineRow.cell.height = { UITableViewAutomaticDimension }\n    }\n}\n```\n\nThe `InlineRowType` will also add some methods to your inline row:\n\n```swift\nfunc expandInlineRow()\nfunc collapseInlineRow()\nfunc toggleInlineRow()\n```\n\nThese methods should work fine but should you want to override them keep in mind that it is `toggleInlineRow` that has to call `expandInlineRow` and `collapseInlineRow`.\n\nFinally you must invoke `toggleInlineRow()` when the row is selected, for example overriding `customDidSelect`:\n\n```swift\npublic override func customDidSelect() {\n    super.customDidSelect()\n    if !isDisabled {\n        toggleInlineRow()\n    }\n}\n```\n\n### Custom Presenter rows\n\n**Note:** *A Presenter row is a row that presents a new UIViewController.*\n\nTo create a custom Presenter row you must create a class that conforms the `PresenterRowType` protocol. It is highly recommended to subclass `SelectorRow` as it does conform to that protocol and adds other useful functionality.\n\nThe PresenterRowType protocol is defined as follows:\n```swift\npublic protocol PresenterRowType: TypedRowType {\n\n     associatedtype PresentedControllerType : UIViewController, TypedRowControllerType\n\n     /// Defines how the view controller will be presented, pushed, etc.\n     var presentationMode: PresentationMode<PresentedControllerType>? { get set }\n\n     /// Will be called before the presentation occurs.\n     var onPresentCallback: ((FormViewController, PresentedControllerType) -> Void)? { get set }\n}\n```\n\nThe onPresentCallback will be called when the row is about to present another view controller. This is done in the `SelectorRow` so if you do not subclass it you will have to call it yourself.\n\nThe `presentationMode` is what defines how the controller is presented and which controller is presented. This presentation can be using a Segue identifier, a segue class, presenting a controller modally or pushing to a specific view controller. For example a CustomPushRow can be defined like this:\n\n\nLet's see an example..\n\n```swift\n\n/// Generic row type where a user must select a value among several options.\nopen class SelectorRow<Cell: CellType>: OptionsRow<Cell>, PresenterRowType where Cell: BaseCell {\n\n\n    /// Defines how the view controller will be presented, pushed, etc.\n    open var presentationMode: PresentationMode<SelectorViewController<SelectorRow<Cell>>>?\n\n    /// Will be called before the presentation occurs.\n    open var onPresentCallback: ((FormViewController, SelectorViewController<SelectorRow<Cell>>) -> Void)?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    /**\n     Extends `didSelect` method\n     */\n    open override func customDidSelect() {\n        super.customDidSelect()\n        guard let presentationMode = presentationMode, !isDisabled else { return }\n        if let controller = presentationMode.makeController() {\n            controller.row = self\n            controller.title = selectorTitle ?? controller.title\n            onPresentCallback?(cell.formViewController()!, controller)\n            presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n        } else {\n            presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n        }\n    }\n\n    /**\n     Prepares the pushed row setting its title and completion callback.\n     */\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as Any as? SelectorViewController<SelectorRow<Cell>> else { return }\n        rowVC.title = selectorTitle ?? rowVC.title\n        rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback\n        onPresentCallback?(cell.formViewController()!, rowVC)\n        rowVC.row = self\n    }\n}\n\n\n// SelectorRow conforms to PresenterRowType\npublic final class CustomPushRow<T: Equatable>: SelectorRow<PushSelectorCell<T>>, RowType {\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        presentationMode = .show(controllerProvider: ControllerProvider.callback {\n            return SelectorViewController<T>(){ _ in }\n            }, onDismiss: { vc in\n                _ = vc.navigationController?.popViewController(animated: true)\n        })\n    }\n}\n```\n\n\n### Subclassing cells using the same row\n\nSometimes we want to change the UI look of one of our rows but without changing the row type and all the logic associated to one row.\nThere is currently one way to do this **if you are using cells that are instantiated from nib files**. Currently, none of Eureka's core rows are instantiated from nib files but some of the custom rows in [EurekaCommunity] are, in particular the [PostalAddressRow](https://github.com/EurekaCommunity/PostalAddressRow) which was moved there.\n\nWhat you have to do is:\n* Create a nib file containing the cell you want to create.\n* Then set the class of the cell to be the existing cell you want to modify (if you want to change something more apart from pure UI then you should subclass that cell). Make sure the module of that class is correctly set\n* Connect the outlets to your class\n* Tell your row to use the new nib file. This is done by setting the `cellProvider` variable to use this nib. You should do this in the initialiser, either in each concrete instantiation or using the `defaultRowInitializer`. For example:\n\n```swift\n<<< PostalAddressRow() {\n     $0.cellProvider = CellProvider<PostalAddressCell>(nibName: \"CustomNib\", bundle: Bundle.main)\n}\n```\n\nYou could also create a new row for this. In that case try to inherit from the same superclass as the row you want to change to inherit its logic.\n\nThere are some things to consider when you do this:\n* If you want to see an example have a look at the [PostalAddressRow](https://github.com/EurekaCommunity/PostalAddressRow) or the [CreditCardRow](https://github.com/EurekaCommunity/CreditCardRow) which have use a custom nib file in their examples.\n* If you get an error saying `Unknown class <YOUR_CLASS_NAME> in Interface Builder file`, it might be that you have to instantiate that new type somewhere in your code to load it in the runtime. Calling `let t = YourClass.self` helped in my case.\n\n\n## Row catalog\n\n### Controls Rows\n<table>\n    <tr>\n        <td><center><b>Label Row</b><br>\n        <img src=\"Example/Media/RowStatics/LabelRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Button Row</b><br>\n        <img src=\"Example/Media/RowStatics/ButtonRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Check Row</b><br>\n        <img src=\"Example/Media/RowStatics/CheckRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n    <tr>\n        <td><center><b>Switch Row</b><br>\n        <img src=\"Example/Media/RowStatics/SwitchRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Slider Row</b><br>\n        <img src=\"Example/Media/RowStatics/SliderRow.png\"/>\n        </center><br><br>\n        </td>\n        <td><center><b>Stepper Row</b><br>\n        <img src=\"Example/Media/RowStatics/StepperRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n    <tr>\n        <td><center><b>Text Area Row</b><br>\n        <img src=\"Example/Media/RowStatics/TextAreaRow.png\"/>\n        </center><br><br>\n        </td>\n    </tr>\n</table>\n\n### Field Rows\nThese rows have a textfield on the right side of the cell. The difference between each one of them consists in a different capitalization, autocorrection and keyboard type configuration.\n\n<table>\n<tr>\n  <td>\n    <img src=\"Example/Media/CatalogFieldRows.jpg\" width=\"300\"/>\n  </td>\n  <td>\n  TextRow<br><br>\n  NameRow<br><br>\n  URLRow<br><br>\n  IntRow<br><br>\n  PhoneRow<br><br>\n  PasswordRow<br><br>\n  EmailRow<br><br>\n  DecimalRow<br><br>\n  TwitterRow<br><br>\n  AccountRow<br><br>\n  ZipCodeRow\n  </td>\n<tr>\n</table>\n\nAll of the `FieldRow` subtypes above have a `formatter` property of type <a href=\"https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSFormatter_Class/\">`NSFormatter`</a> which can be set to determine how that row's value should be displayed. A custom formatter for numbers with two digits after the decimal mark is included with Eureka (`DecimalFormatter`). The Example project also contains a `CurrencyFormatter` which displays a number as currency according to the user's locale.\n\nBy default, setting a row's `formatter` only affects how a value is displayed when it is not being edited. To also format the value while the row is being edited, set `useFormatterDuringInput` to `true` when initializing the row. Formatting the value as it is being edited may require updating the cursor position and Eureka provides the following protocol that your formatter should conform to in order to handle cursor position:\n\n```swift\npublic protocol FormatterProtocol {\n    func getNewPosition(forPosition forPosition: UITextPosition, inTextInput textInput: UITextInput, oldValue: String?, newValue: String?) -> UITextPosition\n}\n```\n\nAdditionally, `FieldRow` subtypes have a `useFormatterOnDidBeginEditing` property. When using a `DecimalRow` with a formatter that allows decimal values and conforms to the user's locale (e.g. `DecimalFormatter`), if `useFormatterDuringInput` is `false`, `useFormatterOnDidBeginEditing` must be set to `true` so that the decimal mark in the value being edited matches the decimal mark on the keyboard.\n\n### Date Rows\n\nDate Rows hold a Date and allow us to set up a new value through UIDatePicker control. The mode of the UIDatePicker and the way how the date picker view is shown is what changes between them.\n<table>\n<tr>\n<td>\n<center><b>Date Row</b>\n<img src=\"Example/Media/RowGifs/EurekaDateRow.gif\" height=\"220\" width=\"230\" />\n<br>\nPicker shown in the keyboard.\n</center>\n</td>\n<td>\n<center><b>Date Row (Inline)</b>\n<img src=\"Example/Media/RowGifs/EurekaDateInlineRow.gif\" height=\"220\" width=\"210\"/>\n<br>\nThe row expands.\n</center>\n</td>\n<td>\n<center><b>Date Row (Picker)</b>\n<img src=\"Example/Media/RowGifs/EurekaDatePickerRow.gif\" height=\"220\" width=\"210\"/>\n<br>\nThe picker is always visible.\n</center>\n</td>\n</tr>\n</table>\n\nWith those 3 styles (Normal, Inline & Picker), Eureka includes:\n\n+ **DateRow**\n+ **TimeRow**\n+ **DateTimeRow**\n+ **CountDownRow**\n\n### Option Rows\nThese are rows with a list of options associated from which the user must choose.\n\n```swift\n<<< ActionSheetRow<String>() {\n                $0.title = \"ActionSheetRow\"\n                $0.selectorTitle = \"Pick a number\"\n                $0.options = [\"One\",\"Two\",\"Three\"]\n                $0.value = \"Two\"    // initially selected\n            }\n```\n\n<table>\n<tr>\n<td width=\"25%\">\n<center><b>Alert Row</b><br>\n<img src=\"Example/Media/RowStatics/AlertRow.jpeg\"/>\n<br>\nWill show an alert with the options to choose from.\n</center>\n</td>\n<td width=\"25%\">\n<center><b>ActionSheet Row</b><br>\n<img src=\"Example/Media/RowStatics/ActionSheetRow.jpeg\"/>\n<br>\nWill show an action sheet with the options to choose from.\n</center>\n</td>\n<td width=\"25%\">\n<center><b>Push Row</b><br>\n<img src=\"Example/Media/RowStatics/PushRow.jpeg\"/>\n<br>\nWill push to a new controller from where to choose options listed using Check rows.\n</center>\n</td>\n<td width=\"25%\">\n<center><b>Multiple Selector Row</b><br>\n<img src=\"Example/Media/RowStatics/MultipleSelectorRow.jpeg\"/>\n<br>\nLike PushRow but allows the selection of multiple options.\n</center>\n</td>\n</tr>\n</table>\n\n<table>\n    <tr>\n        <td><center><b>Segmented Row</b><br>\n        <img src=\"Example/Media/RowStatics/SegmentedRow.png\"/>\n        </center>\n        </td>\n        <td><center><b>Segmented Row (w/Title)</b><br>\n        <img src=\"Example/Media/RowStatics/SegmentedRowWithTitle.png\"/>\n        </center>\n        </td>\n        <td><center><b>Picker Row</b><br>\n        <img src=\"Example/Media/RowStatics/PickerRow.png\"/>\n        <br>Presents options of a generic type through a picker view\n        <br><b>(There is also Picker Inline Row)</b>\n        </center>\n        </td>\n    </tr>\n</table>\n\n### Built your own custom row?\nLet us know about it, we would be glad to mention it here. :)\n\n* **LocationRow** (Included as custom row in the example project)\n\n<img src=\"Example/Media/EurekaLocationRow.gif\" width=\"300\" alt=\"Screenshot of Location Row\"/>\n\n## Installation\n\n#### CocoaPods\n\n[CocoaPods](https://cocoapods.org/) is a dependency manager for Cocoa projects.\n\nSpecify Eureka into your project's `Podfile`:\n\n```ruby\nsource 'https://github.com/CocoaPods/Specs.git'\nplatform :ios, '9.0'\nuse_frameworks!\n\npod 'Eureka'\n```\n\nThen run the following command:\n\n```bash\n$ pod install\n```\n\n#### Swift Package Manager\n\n[Swift Package Manager](https://swift.org/package-manager/) is a tool for managing the distribution of Swift code.\n\nAfter you set up your `Package.swift` manifest file, you can add Eureka as a dependency by adding it to the dependencies value of your `Package.swift`.\n\ndependencies: [\n    .package(url: \"https://github.com/xmartlabs/Eureka.git\", from: \"5.5.0\")\n]\n\n\n#### Carthage\n\n[Carthage](https://github.com/Carthage/Carthage) is a simple, decentralized dependency manager for Cocoa.\n\nSpecify Eureka into your project's `Cartfile`:\n\n```ogdl\ngithub \"xmartlabs/Eureka\" ~> 5.5\n```\n\n#### Manually as Embedded Framework\n\n* Clone Eureka as a git [submodule](http://git-scm.com/docs/git-submodule) by running the following command from your project root git folder.\n\n```bash\n$ git submodule add https://github.com/xmartlabs/Eureka.git\n```\n\n* Open Eureka folder that was created by the previous git submodule command and drag the Eureka.xcodeproj into the Project Navigator of your application's Xcode project.\n\n* Select the Eureka.xcodeproj in the Project Navigator and verify the deployment target matches with your application deployment target.\n\n* Select your project in the Xcode Navigation and then select your application target from the sidebar. Next select the \"General\" tab and click on the + button under the \"Embedded Binaries\" section.\n\n* Select `Eureka.framework` and we are done!\n\n## Getting involved\n\n* If you **want to contribute** please feel free to **submit pull requests**.\n* If you **have a feature request** please **open an issue**.\n* If you **found a bug** check older issues before submitting an issue.\n* If you **need help** or would like to **ask general question**, use [StackOverflow]. (Tag `eureka-forms`).\n\n**Before contribute check the [CONTRIBUTING](CONTRIBUTING.md) file for more info.**\n\nIf you use **Eureka** in your app We would love to hear about it! Drop us a line on [twitter].\n\n## Authors\n\n* [Martin Barreto](https://github.com/mtnBarreto) ([@mtnBarreto](https://twitter.com/mtnBarreto))\n* [Mathias Claassen](https://github.com/mats-claassen) ([@mClaassen26](https://twitter.com/mClaassen26))\n\n## FAQ\n\n#### How to change the text representation of the row value shown in the  cell.\n\nEvery row has the following property:\n\n```swift\n/// Block variable used to get the String that should be displayed for the value of this row.\npublic var displayValueFor: ((T?) -> String?)? = {\n    return $0.map { String(describing: $0) }\n}\n```\n\nYou can set `displayValueFor` according the string value you want to display.\n\n#### How to get a Row using its tag value\n\nWe can get a particular row by invoking any of the following functions exposed by the `Form` class:\n\n```swift\npublic func rowBy<T: Equatable>(tag: String) -> RowOf<T>?\npublic func rowBy<Row: RowType>(tag: String) -> Row?\npublic func rowBy(tag: String) -> BaseRow?\n```\n\nFor instance:\n\n```swift\nlet dateRow : DateRow? = form.rowBy(tag: \"dateRowTag\")\nlet labelRow: LabelRow? = form.rowBy(tag: \"labelRowTag\")\n\nlet dateRow2: Row<DateCell>? = form.rowBy(tag: \"dateRowTag\")\n\nlet labelRow2: BaseRow? = form.rowBy(tag: \"labelRowTag\")\n```\n\n#### How to get a Section using its tag value\n\n```swift\nlet section: Section?  = form.sectionBy(tag: \"sectionTag\")\n```\n\n#### How to set the form values using a dictionary\n\nInvoking `setValues(values: [String: Any?])` which is exposed by `Form` class.\n\nFor example:\n\n```swift\nform.setValues([\"IntRowTag\": 8, \"TextRowTag\": \"Hello world!\", \"PushRowTag\": Company(name:\"Xmartlabs\")])\n```\n\nWhere `\"IntRowTag\"`, `\"TextRowTag\"`, `\"PushRowTag\"` are row tags (each one uniquely identifies a row) and `8`, `\"Hello world!\"`, `Company(name:\"Xmartlabs\")` are the corresponding row value to assign.\n\nThe value type of a row must match with the value type of the corresponding dictionary value otherwise nil will be assigned.\n\nIf the form was already displayed we have to reload the visible rows either by reloading the table view `tableView.reloadData()` or invoking `updateCell()` to each visible row.\n\n#### Row does not update after changing hidden or disabled condition\n\nAfter setting a condition, this condition is not automatically evaluated. If you want it to do so immediately you can call `.evaluateHidden()` or `.evaluateDisabled()`.\n\nThis functions are just called when a row is added to the form and when a row it depends on changes. If the condition is changed when the row is being displayed then it must be reevaluated manually.\n\n#### onCellUnHighlight doesn't get called unless onCellHighlight is also defined\n\nLook at this [issue](https://github.com/xmartlabs/Eureka/issues/96).\n\n#### How to update a Section header/footer\n\n* Set up a new header/footer data ....\n\n```swift\nsection.header = HeaderFooterView(title: \"Header title \\(variable)\") // use String interpolation\n//or\nvar header = HeaderFooterView<UIView>(.class) // most flexible way to set up a header using any view type\nheader.height = { 60 }  // height can be calculated\nheader.onSetupView = { view, section in  // each time the view is about to be displayed onSetupView is invoked.\n    view.backgroundColor = .orange\n}\nsection.header = header\n```\n\n* Reload the Section to perform the changes\n\n```swift\nsection.reload()\n```\n\n#### How to customize Selector and MultipleSelector option cells\n\n`selectableRowSetup`, `selectableRowCellUpdate` and `selectableRowCellSetup` properties are provided to be able to customize SelectorViewController and MultipleSelectorViewController selectable cells.\n\n```swift\nlet row = PushRow<Emoji>() {\n              $0.title = \"PushRow\"\n              $0.options = [💁🏻, 🍐, 👦🏼, 🐗, 🐼, 🐻]\n              $0.value = 👦🏼\n              $0.selectorTitle = \"Choose an Emoji!\"\n          }.onPresent { from, to in\n              to.dismissOnSelection = false\n              to.dismissOnChange = false\n              to.selectableRowSetup = { row in\n                  row.cellProvider = CellProvider<ListCheckCell<Emoji>>(nibName: \"EmojiCell\", bundle: Bundle.main)\n              }\n              to.selectableRowCellUpdate = { cell, row in\n                  cell.textLabel?.text = \"Text \" + row.selectableValue!  // customization\n                  cell.detailTextLabel?.text = \"Detail \" +  row.selectableValue!\n              }\n          }\n\n```\n\n#### Don't want to use Eureka custom operators?\n\nAs we've said `Form` and `Section` types conform to `MutableCollection` and `RangeReplaceableCollection`. A Form is a collection of Sections and a Section is a collection of Rows.\n\n`RangeReplaceableCollection` protocol extension provides many useful methods to modify collection.\n\n```swift\nextension RangeReplaceableCollection {\n    public mutating func append(_ newElement: Self.Element)\n    public mutating func append<S>(contentsOf newElements: S) where S : Sequence, Self.Element == S.Element\n    public mutating func insert(_ newElement: Self.Element, at i: Self.Index)\n    public mutating func insert<S>(contentsOf newElements: S, at i: Self.Index) where S : Collection, Self.Element == S.Element\n    public mutating func remove(at i: Self.Index) -> Self.Element\n    public mutating func removeSubrange(_ bounds: Range<Self.Index>)\n    public mutating func removeFirst(_ n: Int)\n    public mutating func removeFirst() -> Self.Element\n    public mutating func removeAll(keepingCapacity keepCapacity: Bool)\n    public mutating func reserveCapacity(_ n: Self.IndexDistance)\n}\n```\n\nThese methods are used internally to implement the custom operators as shown bellow:\n\n```swift\npublic func +++(left: Form, right: Section) -> Form {\n    left.append(right)\n    return left\n}\n\npublic func +=<C : Collection>(inout lhs: Form, rhs: C) where C.Element == Section {\n    lhs.append(contentsOf: rhs)\n}\n\npublic func <<<(left: Section, right: BaseRow) -> Section {\n    left.append(right)\n    return left\n}\n\npublic func +=<C : Collection>(inout lhs: Section, rhs: C) where C.Element == BaseRow {\n    lhs.append(contentsOf: rhs)\n}\n```\n\nYou can see how the rest of custom operators are implemented [here](https://github.com/xmartlabs/Eureka/blob/master/Source/Core/Operators.swift).\n\nIt's up to you to decide if you want to use Eureka custom operators or not.\n\n#### How to set up your form from a storyboard\nThe form is always displayed in a `UITableView`. You can set up your view controller in a storyboard and add a UITableView where you want it to be and then connect the outlet to FormViewController's `tableView` variable. This allows you to define a custom frame (possibly with constraints) for your form.\n\nAll of this can also be done by programmatically changing frame, margins, etc. of the `tableView` of your FormViewController.\n\n\n<!--- In file -->\n[Introduction]: #introduction\n[Requirements]: #requirements\n\n[How to create a Form]: #how-to-create-a-form\n[Getting row values]: #getting-row-values\n[How to get the form values]: #how-to-get-the-form-values\n[Examples]: #examples\n[Usage]: #usage\n[Operators]: #operators\n[Rows]: #rows\n[Using the callbacks]: #using-the-callbacks\n[Section Header and Footer]: #section-header-and-footer\n[Custom rows]: #custom-rows\n[Basic custom rows]: #basic-custom-rows\n[Custom inline rows]: #custom-inline-rows\n[Custom presenter rows]: #custom-presenter-rows\n[How to create custom inline rows]: #how-to-create-custom-inline-rows\n[Custom rows catalog]: #custom-rows-catalog\n[Dynamically hide and show rows (or sections)]: #hide-show-rows\n[Implementing a custom Presenter row]: #custom-presenter-row\n[Extensibility]: #extensibility\n[Row catalog]: #row-catalog\n[Installation]: #installation\n[FAQ]: #faq\n\n[List sections]: #list-sections\n[Multivalued sections]: #multivalued-sections\n[Validations]: #validations\n[Swipe Actions]: #swipe-actions\n\n<!--- In Project -->\n[CustomCellsController]: Example/Example/ViewController.swift\n[FormViewController]: Example/Source/Controllers.swift\n\n<!--- External -->\n[XLForm]: https://github.com/xmartlabs/XLForm\n[DSL]: https://en.wikipedia.org/wiki/Domain-specific_language\n[StackOverflow]: http://stackoverflow.com/questions/tagged/eureka-forms\n[our blog post]: http://blog.xmartlabs.com/2015/09/29/Introducing-Eureka-iOS-form-library-written-in-pure-Swift/\n[twitter]: https://twitter.com/xmartlabs\n[EurekaCommunity]: https://github.com/EurekaCommunity\n\n# Donate to Eureka\n\nSo we can make Eureka even better!<br><br>\n[<img src=\"donate.png\"/>](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=HRMAH7WZ4QQ8E)\n\n# Change Log\n\nThis can be found in the [CHANGELOG.md](CHANGELOG.md) file.\n"
  },
  {
    "path": "Source/Assets.xcassets/Contents.json",
    "content": "{\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}"
  },
  {
    "path": "Source/Core/BaseRow.swift",
    "content": "//  BaseRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class BaseRow: BaseRowType {\n\n    var callbackOnChange: (() -> Void)?\n    var callbackCellUpdate: (() -> Void)?\n    var callbackCellSetup: Any?\n    var callbackCellOnSelection: (() -> Void)?\n    var callbackOnExpandInlineRow: Any?\n    var callbackOnCollapseInlineRow: Any?\n    var callbackOnCellHighlightChanged: (() -> Void)?\n    var callbackOnRowValidationChanged: (() -> Void)?\n    var _inlineRow: BaseRow?\n\n    var _cachedOptionsData: Any?\n\n    public var validationOptions: ValidationOptions = .validatesOnBlur\n    // validation state\n    public internal(set) var validationErrors = [ValidationError]() {\n        didSet {\n            guard validationErrors != oldValue else { return }\n            RowDefaults.onRowValidationChanged[\"\\(type(of: self))\"]?(baseCell, self)\n            callbackOnRowValidationChanged?()\n            updateCell()\n        }\n    }\n\n    public internal(set) var wasBlurred = false\n    public internal(set) var wasChanged = false\n\n    public var isValid: Bool { return validationErrors.isEmpty }\n    public var isHighlighted: Bool = false\n\n    /// The title will be displayed in the textLabel of the row.\n    public var title: String?\n\n    /// Parameter used when creating the cell for this row.\n    public var cellStyle = UITableViewCell.CellStyle.value1\n\n    /// String that uniquely identifies a row. Must be unique among rows and sections.\n    public var tag: String?\n\n    /// The untyped cell associated to this row.\n    public var baseCell: BaseCell! { return nil }\n\n    /// The untyped value of this row.\n    public var baseValue: Any? {\n        set {}\n        get { return nil }\n    }\n\n    open func validate(quietly: Bool = false) -> [ValidationError] {\n        return []\n    }\n\n    // Reset validation\n    open func cleanValidationErrors() {\n        validationErrors = []\n    }\n\n    public static var estimatedRowHeight: CGFloat = 44.0\n\n    /// Condition that determines if the row should be disabled or not.\n    public var disabled: Condition? {\n        willSet { removeFromDisabledRowObservers() }\n        didSet { addToDisabledRowObservers() }\n    }\n\n    /// Condition that determines if the row should be hidden or not.\n    public var hidden: Condition? {\n        willSet { removeFromHiddenRowObservers() }\n        didSet { addToHiddenRowObservers() }\n    }\n\n    /// Returns if this row is currently disabled or not\n    public var isDisabled: Bool { return disabledCache }\n\n    /// Returns if this row is currently hidden or not\n    public var isHidden: Bool { return hiddenCache }\n\n    /// The section to which this row belongs.\n    open weak var section: Section?\n\t\n    public lazy var trailingSwipe = {[unowned self] in SwipeConfiguration(self)}()\n\t\n    //needs the accessor because if marked directly this throws \"Stored properties cannot be marked potentially unavailable with '@available'\"\n    private lazy var _leadingSwipe = {[unowned self] in SwipeConfiguration(self)}()\n\n    @available(iOS 11,*)\n    public var leadingSwipe: SwipeConfiguration{\n        get { return self._leadingSwipe }\n        set { self._leadingSwipe = newValue }\n    }\n    \n    public required init(tag: String? = nil) {\n        self.tag = tag\n    }\n\n    /**\n     Method that reloads the cell\n     */\n    open func updateCell() {}\n\n    /**\n     Method called when the cell belonging to this row was selected. Must call the corresponding method in its cell.\n     */\n    open func didSelect() {}\n\n    open func prepare(for segue: UIStoryboardSegue) {}\n\n    /**\n     Helps to pick destination part of the cell after scrolling\n     */\n    open var destinationScrollPosition: UITableView.ScrollPosition? = UITableView.ScrollPosition.bottom\n\n    /**\n     Returns the IndexPath where this row is in the current form.\n     */\n    public final var indexPath: IndexPath? {\n        guard let sectionIndex = section?.index, let rowIndex = section?.firstIndex(of: self) else { return nil }\n        return IndexPath(row: rowIndex, section: sectionIndex)\n    }\n\n    var hiddenCache = false\n    var disabledCache = false {\n        willSet {\n            if newValue && !disabledCache {\n                baseCell.cellResignFirstResponder()\n            }\n        }\n    }\n}\n\nextension BaseRow {\n\n    /**\n     Evaluates if the row should be hidden or not and updates the form accordingly\n     */\n    public final func evaluateHidden() {\n        guard let h = hidden, let form = section?.form else { return }\n        switch h {\n        case .function(_, let callback):\n            hiddenCache = callback(form)\n        case .predicate(let predicate):\n            hiddenCache = predicate.evaluate(with: self, substitutionVariables: form.dictionaryValuesToEvaluatePredicate())\n        }\n        if hiddenCache {\n            section?.hide(row: self)\n        } else {\n            section?.show(row: self)\n        }\n    }\n\n    /**\n     Evaluates if the row should be disabled or not and updates it accordingly\n     */\n    public final func evaluateDisabled() {\n        guard let d = disabled, let form = section?.form else { return }\n        switch d {\n        case .function(_, let callback):\n            disabledCache = callback(form)\n        case .predicate(let predicate):\n            disabledCache = predicate.evaluate(with: self, substitutionVariables: form.dictionaryValuesToEvaluatePredicate())\n        }\n        updateCell()\n    }\n\n    final func wasAddedTo(section: Section) {\n        self.section = section\n        if let t = tag {\n            assert(section.form?.rowsByTag[t] == nil, \"Duplicate tag \\(t)\")\n            self.section?.form?.rowsByTag[t] = self\n            self.section?.form?.tagToValues[t] = baseValue != nil ? baseValue! : NSNull()\n        }\n        addToRowObservers()\n        evaluateHidden()\n        evaluateDisabled()\n    }\n\n    final func addToHiddenRowObservers() {\n        guard let h = hidden else { return }\n        switch h {\n        case .function(let tags, _):\n            section?.form?.addRowObservers(to: self, rowTags: tags, type: .hidden)\n        case .predicate(let predicate):\n            section?.form?.addRowObservers(to: self, rowTags: predicate.predicateVars, type: .hidden)\n        }\n    }\n\n    final func addToDisabledRowObservers() {\n        guard let d = disabled else { return }\n        switch d {\n        case .function(let tags, _):\n            section?.form?.addRowObservers(to: self, rowTags: tags, type: .disabled)\n        case .predicate(let predicate):\n            section?.form?.addRowObservers(to: self, rowTags: predicate.predicateVars, type: .disabled)\n        }\n    }\n\n    final func addToRowObservers() {\n        addToHiddenRowObservers()\n        addToDisabledRowObservers()\n    }\n\n    final func willBeRemovedFromForm() {\n        (self as? BaseInlineRowType)?.collapseInlineRow()\n        if let t = tag {\n            section?.form?.rowsByTag[t] = nil\n            section?.form?.tagToValues[t] = nil\n        }\n        removeFromRowObservers()\n    }\n\n    final func willBeRemovedFromSection() {\n        willBeRemovedFromForm()\n        section = nil\n    }\n\n    final func removeFromHiddenRowObservers() {\n        guard let h = hidden else { return }\n        switch h {\n        case .function(let tags, _):\n            section?.form?.removeRowObservers(from: self, rowTags: tags, type: .hidden)\n        case .predicate(let predicate):\n            section?.form?.removeRowObservers(from: self, rowTags: predicate.predicateVars, type: .hidden)\n        }\n    }\n\n    final func removeFromDisabledRowObservers() {\n        guard let d = disabled else { return }\n        switch d {\n        case .function(let tags, _):\n            section?.form?.removeRowObservers(from: self, rowTags: tags, type: .disabled)\n        case .predicate(let predicate):\n            section?.form?.removeRowObservers(from: self, rowTags: predicate.predicateVars, type: .disabled)\n        }\n    }\n\n    final func removeFromRowObservers() {\n        removeFromHiddenRowObservers()\n        removeFromDisabledRowObservers()\n    }\n}\n\nextension BaseRow: Equatable, Hidable, Disableable {}\n\nextension BaseRow {\n\n    public func reload(with rowAnimation: UITableView.RowAnimation = .none) {\n        guard let tableView = baseCell?.formViewController()?.tableView ?? (section?.form?.delegate as? FormViewController)?.tableView, let indexPath = indexPath else { return }\n        tableView.reloadRows(at: [indexPath], with: rowAnimation)\n    }\n\n    public func deselect(animated: Bool = true) {\n        guard let indexPath = indexPath,\n            let tableView = baseCell?.formViewController()?.tableView ?? (section?.form?.delegate as? FormViewController)?.tableView  else { return }\n        tableView.deselectRow(at: indexPath, animated: animated)\n    }\n\n    public func select(animated: Bool = false, scrollPosition: UITableView.ScrollPosition = .none) {\n        guard let indexPath = indexPath,\n            let tableView = baseCell?.formViewController()?.tableView ?? (section?.form?.delegate as? FormViewController)?.tableView  else { return }\n        tableView.selectRow(at: indexPath, animated: animated, scrollPosition: scrollPosition)\n    }\n}\n\npublic func == (lhs: BaseRow, rhs: BaseRow) -> Bool {\n    return lhs === rhs\n}\n"
  },
  {
    "path": "Source/Core/Cell.swift",
    "content": "//  Cell.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// Base class for the Eureka cells\n@objc(EurekaBaseCell)\nopen class BaseCell: UITableViewCell, BaseCellType {\n\n    /// Untyped row associated to this cell.\n    public var baseRow: BaseRow! { return nil }\n\n    /// Block that returns the height for this cell.\n    public var height: (() -> CGFloat)?\n\n    public required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    public required override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    /**\n     Function that returns the FormViewController this cell belongs to.\n     */\n    public func formViewController() -> FormViewController? {\n        var responder: UIResponder? = self\n        while responder != nil {\n            if let formVC = responder as? FormViewController {\n              return formVC\n            }\n            responder = responder?.next\n        }\n        return nil\n    }\n\n    open func setup() {}\n    open func update() {}\n\n    open func didSelect() {}\n\n    /**\n     If the cell can become first responder. By default returns false\n     */\n    open func cellCanBecomeFirstResponder() -> Bool {\n        return false\n    }\n\n    /**\n     Called when the cell becomes first responder\n     */\n    @discardableResult\n    open func cellBecomeFirstResponder(withDirection: Direction = .down) -> Bool {\n        return becomeFirstResponder()\n    }\n\n    /**\n     Called when the cell resigns first responder\n     */\n    @discardableResult\n    open func cellResignFirstResponder() -> Bool {\n        return resignFirstResponder()\n    }\n}\n\n/// Generic class that represents the Eureka cells.\nopen class Cell<T>: BaseCell, TypedCellType where T: Equatable {\n\n    public typealias Value = T\n\n    /// The row associated to this cell\n    public weak var row: RowOf<T>!\n\n    private var updatingCellForTintColorDidChange = false\n\n    /// Returns the navigationAccessoryView if it is defined or calls super if not.\n    override open var inputAccessoryView: UIView? {\n        if let v = formViewController()?.inputAccessoryView(for: row) {\n            return v\n        }\n        return super.inputAccessoryView\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    /**\n     Function responsible for setting up the cell at creation time.\n     */\n    open override func setup() {\n        super.setup()\n    }\n\n    /**\n     Function responsible for updating the cell each time it is reloaded.\n     */\n    open override func update() {\n        super.update()\n        textLabel?.text = row.title\n        if #available(iOS 13.0, *) {\n            textLabel?.textColor = row.isDisabled ? .tertiaryLabel : .label\n        } else {\n            textLabel?.textColor = row.isDisabled ? .gray : .black\n        }\n        detailTextLabel?.text = row.displayValueFor?(row.value) ?? (row as? NoValueDisplayTextConformance)?.noValueDisplayText\n    }\n\n    /**\n     Called when the cell was selected.\n     */\n    open override func didSelect() {}\n\n    override open var canBecomeFirstResponder: Bool {\n        return false\n    }\n\n    open override func becomeFirstResponder() -> Bool {\n        let result = super.becomeFirstResponder()\n        if result {\n            formViewController()?.beginEditing(of: self)\n        }\n        return result\n    }\n\n    open override func resignFirstResponder() -> Bool {\n        let result = super.resignFirstResponder()\n        if result {\n            formViewController()?.endEditing(of: self)\n        }\n        return result\n    }\n\n    open override func tintColorDidChange() {\n        super.tintColorDidChange()\n\n        /* Protection from infinite recursion in case an update method changes the tintColor */\n        if !updatingCellForTintColorDidChange && row != nil {\n            updatingCellForTintColorDidChange = true\n            row.updateCell()\n            updatingCellForTintColorDidChange = false\n        }\n    }\n\n    /// The untyped row associated to this cell.\n    public override var baseRow: BaseRow! { return row }\n}\n"
  },
  {
    "path": "Source/Core/CellType.swift",
    "content": "//  CellType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: Cell Protocols\n\npublic protocol BaseCellType : AnyObject {\n\n    /// Method that will return the height of the cell\n    var height : (() -> CGFloat)? { get }\n\n    /**\n     Method called once when creating a cell. Responsible for setting up the cell.\n     */\n    func setup()\n\n    /**\n     Method called each time the cell is updated (e.g. 'cellForRowAtIndexPath' is called). Responsible for updating the cell.\n     */\n    func update()\n\n    /**\n     Method called each time the cell is selected (tapped on by the user).\n     */\n    func didSelect()\n\n    /**\n     Called when cell is about to become first responder\n     \n     - returns: If the cell should become first responder.\n     */\n    func cellCanBecomeFirstResponder() -> Bool\n\n    /**\n     Method called when the cell becomes first responder\n     */\n    func cellBecomeFirstResponder(withDirection: Direction) -> Bool\n\n    /**\n     Method called when the cell resigns first responder\n     */\n    func cellResignFirstResponder() -> Bool\n\n    /**\n     A reference to the controller in which the cell is displayed.\n     */\n    func formViewController () -> FormViewController?\n}\n\npublic protocol TypedCellType: BaseCellType {\n\n    associatedtype Value: Equatable\n\n    /// The row associated to this cell.\n    var row: RowOf<Value>! { get set }\n}\n\npublic protocol CellType: TypedCellType {}\n"
  },
  {
    "path": "Source/Core/Core.swift",
    "content": "//  Core.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: Row\n\ninternal class RowDefaults {\n    static var cellUpdate = [String: (BaseCell, BaseRow) -> Void]()\n    static var cellSetup = [String: (BaseCell, BaseRow) -> Void]()\n    static var onCellHighlightChanged = [String: (BaseCell, BaseRow) -> Void]()\n    static var rowInitialization = [String: (BaseRow) -> Void]()\n    static var onRowValidationChanged = [String: (BaseCell, BaseRow) -> Void]()\n    static var rawCellUpdate = [String: Any]()\n    static var rawCellSetup = [String: Any]()\n    static var rawOnCellHighlightChanged = [String: Any]()\n    static var rawRowInitialization = [String: Any]()\n    static var rawOnRowValidationChanged = [String: Any]()\n}\n\n// MARK: FormCells\n\npublic struct CellProvider<Cell: BaseCell> where Cell: CellType {\n\n    /// Nibname of the cell that will be created.\n    public private (set) var nibName: String?\n\n    /// Bundle from which to get the nib file.\n    public private (set) var bundle: Bundle!\n\n    public init() {}\n\n    public init(nibName: String, bundle: Bundle? = nil) {\n        self.nibName = nibName\n        self.bundle = bundle ?? Bundle(for: Cell.self)\n    }\n\n    /**\n     Creates the cell with the specified style.\n\n     - parameter cellStyle: The style with which the cell will be created.\n\n     - returns: the cell\n     */\n    func makeCell(style: UITableViewCell.CellStyle) -> Cell {\n        if let nibName = self.nibName {\n            return bundle.loadNibNamed(nibName, owner: nil, options: nil)!.first as! Cell\n        }\n        return Cell.init(style: style, reuseIdentifier: nil)\n    }\n}\n\n/**\n Enumeration that defines how a controller should be created.\n\n - Callback->VCType: Creates the controller inside the specified block\n - NibFile:          Loads a controller from a nib file in some bundle\n - StoryBoard:       Loads the controller from a Storyboard by its storyboard id\n */\npublic enum ControllerProvider<VCType: UIViewController> {\n\n    /**\n     *  Creates the controller inside the specified block\n     */\n    case callback(builder: (() -> VCType))\n\n    /**\n     *  Loads a controller from a nib file in some bundle\n     */\n    case nibFile(name: String, bundle: Bundle?)\n\n    /**\n     *  Loads the controller from a Storyboard by its storyboard id\n     */\n    case storyBoard(storyboardId: String, storyboardName: String, bundle: Bundle?)\n\n    func makeController() -> VCType {\n        switch self {\n            case .callback(let builder):\n                return builder()\n            case .nibFile(let nibName, let bundle):\n                return VCType.init(nibName: nibName, bundle:bundle ?? Bundle(for: VCType.self))\n            case .storyBoard(let storyboardId, let storyboardName, let bundle):\n                let sb = UIStoryboard(name: storyboardName, bundle: bundle ?? Bundle(for: VCType.self))\n                return sb.instantiateViewController(withIdentifier: storyboardId) as! VCType\n        }\n    }\n}\n\n/**\n Defines how a controller should be presented.\n\n - Show?:           Shows the controller with `showViewController(...)`.\n - PresentModally?: Presents the controller modally.\n - SegueName?:      Performs the segue with the specified identifier (name).\n - SegueClass?:     Performs a segue from a segue class.\n */\npublic enum PresentationMode<VCType: UIViewController> {\n\n    /**\n     *  Shows the controller, created by the specified provider, with `showViewController(...)`.\n     */\n    case show(controllerProvider: ControllerProvider<VCType>, onDismiss: ((UIViewController) -> Void)?)\n\n    /**\n     *  Presents the controller, created by the specified provider, modally.\n     */\n    case presentModally(controllerProvider: ControllerProvider<VCType>, onDismiss: ((UIViewController) -> Void)?)\n\n    /**\n     *  Performs the segue with the specified identifier (name).\n     */\n    case segueName(segueName: String, onDismiss: ((UIViewController) -> Void)?)\n\n    /**\n     *  Performs a segue from a segue class.\n     */\n    case segueClass(segueClass: UIStoryboardSegue.Type, onDismiss: ((UIViewController) -> Void)?)\n\n    case popover(controllerProvider: ControllerProvider<VCType>, onDismiss: ((UIViewController) -> Void)?)\n\n    public var onDismissCallback: ((UIViewController) -> Void)? {\n        switch self {\n            case .show(_, let completion):\n                return completion\n            case .presentModally(_, let completion):\n                return completion\n            case .segueName(_, let completion):\n                return completion\n            case .segueClass(_, let completion):\n                return completion\n            case .popover(_, let completion):\n                return completion\n        }\n    }\n\n    /**\n     Present the view controller provided by PresentationMode. Should only be used from custom row implementation.\n\n     - parameter viewController:           viewController to present if it makes sense (normally provided by makeController method)\n     - parameter row:                      associated row\n     - parameter presentingViewController: form view controller\n     */\n    public func present(_ viewController: VCType!, row: BaseRow, presentingController: FormViewController) {\n        switch self {\n            case .show(_, _):\n                presentingController.show(viewController, sender: row)\n            case .presentModally(_, _):\n                presentingController.present(viewController, animated: true)\n            case .segueName(let segueName, _):\n                presentingController.performSegue(withIdentifier: segueName, sender: row)\n            case .segueClass(let segueClass, _):\n                let segue = segueClass.init(identifier: row.tag, source: presentingController, destination: viewController)\n                presentingController.prepare(for: segue, sender: row)\n                segue.perform()\n            case .popover(_, _):\n                guard let porpoverController = viewController.popoverPresentationController else {\n                    fatalError()\n                }\n                porpoverController.sourceView = porpoverController.sourceView ?? presentingController.tableView\n                presentingController.present(viewController, animated: true)\n            }\n\n    }\n\n    /**\n     Creates the view controller specified by presentation mode. Should only be used from custom row implementation.\n\n     - returns: the created view controller or nil depending on the PresentationMode type.\n     */\n    public func makeController() -> VCType? {\n        switch self {\n            case .show(let controllerProvider, let completionCallback):\n                let controller = controllerProvider.makeController()\n                let completionController = controller as? RowControllerType\n                if let callback = completionCallback {\n                    completionController?.onDismissCallback = callback\n                }\n                return controller\n            case .presentModally(let controllerProvider, let completionCallback):\n                let controller = controllerProvider.makeController()\n                let completionController = controller as? RowControllerType\n                if let callback = completionCallback {\n                    completionController?.onDismissCallback = callback\n                }\n                return controller\n            case .popover(let controllerProvider, let completionCallback):\n                let controller = controllerProvider.makeController()\n                controller.modalPresentationStyle = .popover\n                let completionController = controller as? RowControllerType\n                if let callback = completionCallback {\n                    completionController?.onDismissCallback = callback\n                }\n                return controller\n            default:\n                return nil\n        }\n    }\n}\n\n/**\n *  Protocol to be implemented by custom formatters.\n */\npublic protocol FormatterProtocol {\n    func getNewPosition(forPosition: UITextPosition, inTextInput textInput: UITextInput, oldValue: String?, newValue: String?) -> UITextPosition\n}\n\n// MARK: Predicate Machine\n\nenum ConditionType {\n    case hidden, disabled\n}\n\n/**\n Enumeration that are used to specify the disbaled and hidden conditions of rows\n\n - Function:  A function that calculates the result\n - Predicate: A predicate that returns the result\n */\npublic enum Condition {\n    /**\n     *  Calculate the condition inside a block\n     *\n     *  @param            Array of tags of the rows this function depends on\n     *  @param Form->Bool The block that calculates the result\n     *\n     *  @return If the condition is true or false\n     */\n    case function([String], (Form)->Bool)\n\n    /**\n     *  Calculate the condition using a NSPredicate\n     *\n     *  @param NSPredicate The predicate that will be evaluated\n     *\n     *  @return If the condition is true or false\n     */\n    case predicate(NSPredicate)\n}\n\nextension Condition : ExpressibleByBooleanLiteral {\n\n    /**\n     Initialize a condition to return afixed boolean value always\n     */\n    public init(booleanLiteral value: Bool) {\n        self = Condition.function([]) { _ in return value }\n    }\n}\n\nextension Condition : ExpressibleByStringLiteral {\n\n    /**\n     Initialize a Condition with a string that will be converted to a NSPredicate\n     */\n    public init(stringLiteral value: String) {\n        self = .predicate(NSPredicate(format: value))\n    }\n\n    /**\n     Initialize a Condition with a string that will be converted to a NSPredicate\n     */\n    public init(unicodeScalarLiteral value: String) {\n        self = .predicate(NSPredicate(format: value))\n    }\n\n    /**\n     Initialize a Condition with a string that will be converted to a NSPredicate\n     */\n    public init(extendedGraphemeClusterLiteral value: String) {\n        self = .predicate(NSPredicate(format: value))\n    }\n}\n\n// MARK: Errors\n\n/**\nErrors thrown by Eureka\n\n - duplicatedTag: When a section or row is inserted whose tag dows already exist\n - rowNotInSection: When a row was expected to be in a Section, but is not.\n*/\npublic enum EurekaError: Error {\n    case duplicatedTag(tag: String)\n    case rowNotInSection(row: BaseRow)\n}\n\n//Mark: FormViewController\n\n/**\n*  A protocol implemented by FormViewController\n*/\npublic protocol FormViewControllerProtocol {\n    var tableView: UITableView! { get }\n\n    func beginEditing<T>(of: Cell<T>)\n    func endEditing<T>(of: Cell<T>)\n\n    func insertAnimation(forRows rows: [BaseRow]) -> UITableView.RowAnimation\n    func deleteAnimation(forRows rows: [BaseRow]) -> UITableView.RowAnimation\n    func reloadAnimation(oldRows: [BaseRow], newRows: [BaseRow]) -> UITableView.RowAnimation\n    func insertAnimation(forSections sections: [Section]) -> UITableView.RowAnimation\n    func deleteAnimation(forSections sections: [Section]) -> UITableView.RowAnimation\n    func reloadAnimation(oldSections: [Section], newSections: [Section]) -> UITableView.RowAnimation\n}\n\n/**\n *  Navigation options for a form view controller.\n */\npublic struct RowNavigationOptions: OptionSet {\n\n    private enum NavigationOptions: Int {\n        case disabled = 0, enabled = 1, stopDisabledRow = 2, skipCanNotBecomeFirstResponderRow = 4\n    }\n    public let rawValue: Int\n    public  init(rawValue: Int) { self.rawValue = rawValue}\n    private init(_ options: NavigationOptions ) { self.rawValue = options.rawValue }\n\n    /// No navigation.\n    public static let Disabled = RowNavigationOptions(.disabled)\n\n    /// Full navigation.\n    public static let Enabled = RowNavigationOptions(.enabled)\n\n    /// Break navigation when next row is disabled.\n    public static let StopDisabledRow = RowNavigationOptions(.stopDisabledRow)\n\n    /// Break navigation when next row cannot become first responder.\n    public static let SkipCanNotBecomeFirstResponderRow = RowNavigationOptions(.skipCanNotBecomeFirstResponderRow)\n}\n\n/**\n *  Defines the configuration for the keyboardType of FieldRows.\n */\npublic struct KeyboardReturnTypeConfiguration {\n    /// Used when the next row is available.\n    public var nextKeyboardType = UIReturnKeyType.next\n\n    /// Used if next row is not available.\n    public var defaultKeyboardType = UIReturnKeyType.default\n\n    public init() {}\n\n    public init(nextKeyboardType: UIReturnKeyType, defaultKeyboardType: UIReturnKeyType) {\n        self.nextKeyboardType = nextKeyboardType\n        self.defaultKeyboardType = defaultKeyboardType\n    }\n}\n\n/**\n *  Options that define when an inline row should collapse.\n */\npublic struct InlineRowHideOptions: OptionSet {\n\n    private enum _InlineRowHideOptions: Int {\n        case never = 0, anotherInlineRowIsShown = 1, firstResponderChanges = 2\n    }\n    public let rawValue: Int\n    public init(rawValue: Int) { self.rawValue = rawValue}\n    private init(_ options: _InlineRowHideOptions ) { self.rawValue = options.rawValue }\n\n    /// Never collapse automatically. Only when user taps inline row.\n    public static let Never = InlineRowHideOptions(.never)\n\n    /// Collapse qhen another inline row expands. Just one inline row will be expanded at a time.\n    public static let AnotherInlineRowIsShown = InlineRowHideOptions(.anotherInlineRowIsShown)\n\n    /// Collapse when first responder changes.\n    public static let FirstResponderChanges = InlineRowHideOptions(.firstResponderChanges)\n}\n\n/// View controller that shows a form.\n@objc(EurekaFormViewController)\nopen class FormViewController: UIViewController, FormViewControllerProtocol, FormDelegate {\n\n    @IBOutlet public var tableView: UITableView!\n\n    private lazy var _form: Form = { [weak self] in\n        let form = Form()\n        form.delegate = self\n        return form\n        }()\n\n    public var form: Form {\n        get { return _form }\n        set {\n            guard form !== newValue else { return }\n            _form.delegate = nil\n            tableView?.endEditing(false)\n            _form = newValue\n            _form.delegate = self\n            if isViewLoaded {\n                tableView?.reloadData()\n            }\n        }\n    }\n\n    /// Extra space to leave between between the row in focus and the keyboard\n    open var rowKeyboardSpacing: CGFloat = 0\n\n    /// Enables animated scrolling on row navigation\n    open var animateScroll = false\n    \n    /// The default scroll position on the focussed cell when keyboard appears\n    open var defaultScrollPosition = UITableView.ScrollPosition.none\n\n    /// Accessory view that is responsible for the navigation between rows\n    private var navigationAccessoryView: (UIView & NavigationAccessory)!\n\n    /// Custom Accesory View to be used as a replacement\n    open var customNavigationAccessoryView: (UIView & NavigationAccessory)? {\n        return nil\n    }\n\n    /// Defines the behaviour of the navigation between rows\n    public var navigationOptions: RowNavigationOptions?\n    public var tableViewStyle: UITableView.Style = .grouped\n\n    public init(style: UITableView.Style) {\n        super.init(nibName: nil, bundle: nil)\n        tableViewStyle = style\n    }\n\n    public override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    }\n\n    public required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func viewDidLoad() {\n        super.viewDidLoad()\n        navigationAccessoryView = customNavigationAccessoryView ?? NavigationAccessoryView(frame: CGRect(x: 0, y: 0, width: view.frame.width, height: 44.0))\n        navigationAccessoryView.autoresizingMask = .flexibleWidth\n\n        if tableView == nil {\n            tableView = UITableView(frame: view.bounds, style: tableViewStyle)\n            tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]\n            tableView.cellLayoutMarginsFollowReadableWidth = false\n        }\n        if tableView.superview == nil {\n            view.addSubview(tableView)\n        }\n        if tableView.delegate == nil {\n            tableView.delegate = self\n        }\n        if tableView.dataSource == nil {\n            tableView.dataSource = self\n        }\n        tableView.rowHeight = UITableView.automaticDimension\n        tableView.estimatedRowHeight = BaseRow.estimatedRowHeight\n        tableView.allowsSelectionDuringEditing = true\n    }\n\n    open override func viewWillAppear(_ animated: Bool) {\n        super.viewWillAppear(animated)\n        animateTableView = true\n        let selectedIndexPaths = tableView.indexPathsForSelectedRows ?? []\n        if !selectedIndexPaths.isEmpty {\n            if #available(iOS 13.0, *) {\n                if tableView.window != nil {\n                    tableView.reloadRows(at: selectedIndexPaths, with: .none)\n                }\n            } else {\n                tableView.reloadRows(at: selectedIndexPaths, with: .none)\n            }\n        }\n        selectedIndexPaths.forEach {\n            tableView.selectRow(at: $0, animated: false, scrollPosition: .none)\n        }\n\n        let deselectionAnimation = { [weak self] (context: UIViewControllerTransitionCoordinatorContext) in\n            selectedIndexPaths.forEach {\n                self?.tableView.deselectRow(at: $0, animated: context.isAnimated)\n            }\n        }\n\n        let reselection = { [weak self] (context: UIViewControllerTransitionCoordinatorContext) in\n            if context.isCancelled {\n                selectedIndexPaths.forEach {\n                    self?.tableView.selectRow(at: $0, animated: false, scrollPosition: .none)\n                }\n            }\n        }\n\n        if let coordinator = transitionCoordinator {\n            coordinator.animate(alongsideTransition: deselectionAnimation, completion: reselection)\n        } else {\n            selectedIndexPaths.forEach {\n                tableView.deselectRow(at: $0, animated: false)\n            }\n        }\n\n        NotificationCenter.default.addObserver(self, selector: #selector(FormViewController.keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)\n        NotificationCenter.default.addObserver(self, selector: #selector(FormViewController.keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)\n\n        if form.containsMultivaluedSection && (isBeingPresented || isMovingToParent) {\n            tableView.setEditing(true, animated: false)\n        }\n    }\n\n    open override func viewWillDisappear(_ animated: Bool) {\n        super.viewWillDisappear(animated)\n        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)\n        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)\n    }\n\n    open override func prepare(for segue: UIStoryboardSegue, sender: Any?) {\n        super.prepare(for: segue, sender: sender)\n        let baseRow = sender as? BaseRow\n        baseRow?.prepare(for: segue)\n    }\n\n    /**\n     Returns the navigation accessory view if it is enabled. Returns nil otherwise.\n     */\n    open func inputAccessoryView(for row: BaseRow) -> UIView? {\n        let options = navigationOptions ?? Form.defaultNavigationOptions\n        guard options.contains(.Enabled) else { return nil }\n        guard row.baseCell.cellCanBecomeFirstResponder() else { return nil}\n        navigationAccessoryView.previousEnabled = nextRow(for: row, withDirection: .up) != nil\n        navigationAccessoryView.doneClosure = { [weak self] in\n            self?.navigationDone()\n        }\n        navigationAccessoryView.previousClosure = { [weak self] in\n            self?.navigationPrevious()\n        }\n        navigationAccessoryView.nextClosure = { [weak self] in\n            self?.navigationNext()\n        }\n        navigationAccessoryView.nextEnabled = nextRow(for: row, withDirection: .down) != nil\n        return navigationAccessoryView\n    }\n\n    // MARK: FormViewControllerProtocol\n\n    /**\n    Called when a cell becomes first responder\n    */\n    public final func beginEditing<T>(of cell: Cell<T>) {\n        cell.row.isHighlighted = true\n        cell.row.updateCell()\n        RowDefaults.onCellHighlightChanged[\"\\(type(of: cell.row!))\"]?(cell, cell.row)\n        cell.row.callbackOnCellHighlightChanged?()\n        guard let _ = tableView, (form.inlineRowHideOptions ?? Form.defaultInlineRowHideOptions).contains(.FirstResponderChanges) else { return }\n        let row = cell.baseRow\n        let inlineRow = row?._inlineRow\n        for row in form.allRows.filter({ $0 !== row && $0 !== inlineRow && $0._inlineRow != nil }) {\n            if let inlineRow = row as? BaseInlineRowType {\n                inlineRow.collapseInlineRow()\n            }\n        }\n    }\n\n    /**\n     Called when a cell resigns first responder\n     */\n    public final func endEditing<T>(of cell: Cell<T>) {\n        cell.row.isHighlighted = false\n        cell.row.wasBlurred = true\n        RowDefaults.onCellHighlightChanged[\"\\(type(of: cell.row!))\"]?(cell, cell.row)\n        cell.row.callbackOnCellHighlightChanged?()\n        if cell.row.validationOptions.contains(.validatesOnBlur) || (cell.row.wasChanged && cell.row.validationOptions.contains(.validatesOnChangeAfterBlurred)) {\n            cell.row.validate()\n        }\n        cell.row.updateCell()\n    }\n\n    /**\n     Returns the animation for the insertion of the given rows.\n     */\n    open func insertAnimation(forRows rows: [BaseRow]) -> UITableView.RowAnimation {\n        return .fade\n    }\n\n    /**\n     Returns the animation for the deletion of the given rows.\n     */\n    open func deleteAnimation(forRows rows: [BaseRow]) -> UITableView.RowAnimation {\n        return .fade\n    }\n\n    /**\n     Returns the animation for the reloading of the given rows.\n     */\n    open func reloadAnimation(oldRows: [BaseRow], newRows: [BaseRow]) -> UITableView.RowAnimation {\n        return .automatic\n    }\n\n    /**\n     Returns the animation for the insertion of the given sections.\n     */\n    open func insertAnimation(forSections sections: [Section]) -> UITableView.RowAnimation {\n        return .automatic\n    }\n\n    /**\n     Returns the animation for the deletion of the given sections.\n     */\n    open func deleteAnimation(forSections sections: [Section]) -> UITableView.RowAnimation {\n        return .automatic\n    }\n\n    /**\n     Returns the animation for the reloading of the given sections.\n     */\n    open func reloadAnimation(oldSections: [Section], newSections: [Section]) -> UITableView.RowAnimation {\n        return .automatic\n    }\n\n    // MARK: TextField and TextView Delegate\n\n    open func textInputShouldBeginEditing<T>(_ textInput: UITextInput, cell: Cell<T>) -> Bool {\n        return true\n    }\n\n    open func textInputDidBeginEditing<T>(_ textInput: UITextInput, cell: Cell<T>) {\n        if let row = cell.row as? KeyboardReturnHandler {\n            let next = nextRow(for: cell.row, withDirection: .down)\n            if let textField = textInput as? UITextField {\n                textField.returnKeyType = next != nil ? (row.keyboardReturnType?.nextKeyboardType ??\n                    (form.keyboardReturnType?.nextKeyboardType ?? Form.defaultKeyboardReturnType.nextKeyboardType )) :\n                    (row.keyboardReturnType?.defaultKeyboardType ?? (form.keyboardReturnType?.defaultKeyboardType ??\n                        Form.defaultKeyboardReturnType.defaultKeyboardType))\n            } else if let textView = textInput as? UITextView {\n                textView.returnKeyType = next != nil ? (row.keyboardReturnType?.nextKeyboardType ??\n                    (form.keyboardReturnType?.nextKeyboardType ?? Form.defaultKeyboardReturnType.nextKeyboardType )) :\n                    (row.keyboardReturnType?.defaultKeyboardType ?? (form.keyboardReturnType?.defaultKeyboardType ??\n                        Form.defaultKeyboardReturnType.defaultKeyboardType))\n            }\n        }\n    }\n\n    open func textInputShouldEndEditing<T>(_ textInput: UITextInput, cell: Cell<T>) -> Bool {\n        return true\n    }\n\n    open func textInputDidEndEditing<T>(_ textInput: UITextInput, cell: Cell<T>) {\n\n    }\n\n    open func textInput<T>(_ textInput: UITextInput, shouldChangeCharactersInRange range: NSRange, replacementString string: String, cell: Cell<T>) -> Bool {\n        return true\n    }\n\n    open func textInputShouldClear<T>(_ textInput: UITextInput, cell: Cell<T>) -> Bool {\n        return true\n    }\n\n    open func textInputShouldReturn<T>(_ textInput: UITextInput, cell: Cell<T>) -> Bool {\n        if let nextRow = nextRow(for: cell.row, withDirection: .down) {\n            if nextRow.baseCell.cellCanBecomeFirstResponder() {\n                nextRow.baseCell.cellBecomeFirstResponder()\n                return true\n            }\n        }\n        tableView?.endEditing(true)\n        return true\n    }\n\n    // MARK: FormDelegate\n\n    open func valueHasBeenChanged(for: BaseRow, oldValue: Any?, newValue: Any?) {}\n\n    // MARK: UITableViewDelegate\n\n    @objc open func tableView(_ tableView: UITableView, willBeginReorderingRowAtIndexPath indexPath: IndexPath) {\n        // end editing if inline cell is first responder\n        let row = form[indexPath]\n        if let inlineRow = row as? BaseInlineRowType, row._inlineRow != nil {\n            inlineRow.collapseInlineRow()\n        }\n    }\n\n    // MARK: FormDelegate\n\n    open func sectionsHaveBeenAdded(_ sections: [Section], at indexes: IndexSet) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.insertSections(indexes, with: insertAnimation(forSections: sections))\n        tableView?.endUpdates()\n    }\n\n    open func sectionsHaveBeenRemoved(_ sections: [Section], at indexes: IndexSet) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.deleteSections(indexes, with: deleteAnimation(forSections: sections))\n        tableView?.endUpdates()\n    }\n\n    open func sectionsHaveBeenReplaced(oldSections: [Section], newSections: [Section], at indexes: IndexSet) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.reloadSections(indexes, with: reloadAnimation(oldSections: oldSections, newSections: newSections))\n        tableView?.endUpdates()\n    }\n\n    open func rowsHaveBeenAdded(_ rows: [BaseRow], at indexes: [IndexPath]) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.insertRows(at: indexes, with: insertAnimation(forRows: rows))\n        tableView?.endUpdates()\n    }\n\n    open func rowsHaveBeenRemoved(_ rows: [BaseRow], at indexes: [IndexPath]) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.deleteRows(at: indexes, with: deleteAnimation(forRows: rows))\n        tableView?.endUpdates()\n    }\n\n    open func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at indexes: [IndexPath]) {\n        guard animateTableView else { return }\n        tableView?.beginUpdates()\n        tableView?.reloadRows(at: indexes, with: reloadAnimation(oldRows: oldRows, newRows: newRows))\n        tableView?.endUpdates()\n    }\n\n    // MARK: Private\n\n    var oldBottomInset: CGFloat?\n    var animateTableView = false\n\n    /** Calculates the height needed for a header or footer. */\n    fileprivate func height(specifiedHeight: (() -> CGFloat)?, sectionView: UIView?, sectionTitle: String?) -> CGFloat {\n        if let height = specifiedHeight {\n            return height()\n        }\n\n        if let sectionView = sectionView {\n            let height = sectionView.bounds.height\n\n            if height == 0 {\n                return UITableView.automaticDimension\n            }\n\n            return height\n        }\n\n        if let sectionTitle = sectionTitle,\n            sectionTitle != \"\" {\n            return UITableView.automaticDimension\n        }\n\n        // Fix for iOS 11+. By returning 0, we ensure that no section header or\n        // footer is shown when self-sizing is enabled (i.e. when\n        // tableView.estimatedSectionHeaderHeight or tableView.estimatedSectionFooterHeight\n        // == UITableView.automaticDimension).\n        if tableView.style == .plain {\n            return 0\n        }\n\n        return UITableView.automaticDimension\n    }\n}\n\nextension FormViewController : UITableViewDelegate {\n\n    // MARK: UITableViewDelegate\n\n    open func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {\n        return indexPath\n    }\n\n    open func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {\n        guard tableView == self.tableView else { return }\n        let row = form[indexPath]\n        // row.baseCell.cellBecomeFirstResponder() may be cause InlineRow collapsed then section count will be changed. Use orignal indexPath will out of  section's bounds.\n        if !row.baseCell.cellCanBecomeFirstResponder() || !row.baseCell.cellBecomeFirstResponder() {\n            self.tableView?.endEditing(true)\n        }\n        row.didSelect()\n    }\n\n    open func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {\n        guard tableView == self.tableView else { return tableView.rowHeight }\n        let row = form[indexPath.section][indexPath.row]\n        return row.baseCell.height?() ?? tableView.rowHeight\n    }\n\n    open func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {\n        guard tableView == self.tableView else { return tableView.estimatedRowHeight }\n        let row = form[indexPath.section][indexPath.row]\n        return row.baseCell.height?() ?? tableView.estimatedRowHeight\n    }\n\n    open func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {\n        return form[section].header?.viewForSection(form[section], type: .header)\n    }\n\n    open func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {\n        return form[section].footer?.viewForSection(form[section], type:.footer)\n    }\n\n    open func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {\n        return height(specifiedHeight: form[section].header?.height,\n                      sectionView: self.tableView(tableView, viewForHeaderInSection: section),\n                      sectionTitle: self.tableView(tableView, titleForHeaderInSection: section))\n    }\n\n    open func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {\n        return height(specifiedHeight: form[section].footer?.height,\n                      sectionView: self.tableView(tableView, viewForFooterInSection: section),\n                      sectionTitle: self.tableView(tableView, titleForFooterInSection: section))\n    }\n\n    open func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {\n\t\tlet row = form[indexPath]\n        guard !row.isDisabled else { return false }\n\t\tif row.trailingSwipe.actions.count > 0 { return true }\n\t\tif #available(iOS 11,*), row.leadingSwipe.actions.count > 0 { return true }\n\t\tguard let section = form[indexPath.section] as? BaseMultivaluedSection else { return false }\n        guard !(indexPath.row == section.count - 1 && section.multivaluedOptions.contains(.Insert) && section.showInsertIconInAddButton) else {\n            return true\n        }\n        if indexPath.row > 0 && section[indexPath.row - 1] is BaseInlineRowType && section[indexPath.row - 1]._inlineRow != nil {\n            return false\n        }\n        return true\n    }\n\n    open func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {\n        if editingStyle == .delete {\n            let row = form[indexPath]\n            let section = row.section!\n            if let _ = row.baseCell.findFirstResponder() {\n                tableView.endEditing(true)\n            }\n            section.remove(at: indexPath.row)\n        } else if editingStyle == .insert {\n            guard var section = form[indexPath.section] as? BaseMultivaluedSection else { return }\n            guard let multivaluedRowToInsertAt = section.multivaluedRowToInsertAt else {\n                fatalError(\"Multivalued section multivaluedRowToInsertAt property must be set up\")\n            }\n            let newRow = multivaluedRowToInsertAt(max(0, section.count - 1))\n            section.insert(newRow, at: max(0, section.count - 1))\n            DispatchQueue.main.async {\n                tableView.isEditing = !tableView.isEditing\n                tableView.isEditing = !tableView.isEditing\n            }\n            tableView.scrollToRow(at: IndexPath(row: section.count - 1, section: indexPath.section), at: .bottom, animated: true)\n            if newRow.baseCell.cellCanBecomeFirstResponder() {\n                newRow.baseCell.cellBecomeFirstResponder()\n            } else if let inlineRow = newRow as? BaseInlineRowType {\n                inlineRow.expandInlineRow()\n            }\n        }\n    }\n\n    open func tableView(_ tableView: UITableView, canMoveRowAt indexPath: IndexPath) -> Bool {\n        guard let section = form[indexPath.section] as? BaseMultivaluedSection, section.multivaluedOptions.contains(.Reorder) && section.count > 1 else {\n            return false\n        }\n        if section.multivaluedOptions.contains(.Insert) && (section.count <= 2 || indexPath.row == (section.count - 1)) {\n            return false\n        }\n        if indexPath.row > 0 && section[indexPath.row - 1] is BaseInlineRowType && section[indexPath.row - 1]._inlineRow != nil {\n            return false\n        }\n        return true\n    }\n\n    open func tableView(_ tableView: UITableView, targetIndexPathForMoveFromRowAt sourceIndexPath: IndexPath, toProposedIndexPath proposedDestinationIndexPath: IndexPath) -> IndexPath {\n        guard let section = form[sourceIndexPath.section] as? BaseMultivaluedSection else { return sourceIndexPath }\n        guard sourceIndexPath.section == proposedDestinationIndexPath.section else { return sourceIndexPath }\n\n        let destRow = form[proposedDestinationIndexPath]\n        if destRow is BaseInlineRowType && destRow._inlineRow != nil {\n            return IndexPath(row: proposedDestinationIndexPath.row + (sourceIndexPath.row < proposedDestinationIndexPath.row ? 1 : -1), section:sourceIndexPath.section)\n        }\n\n        if proposedDestinationIndexPath.row > 0 {\n            let previousRow = form[IndexPath(row: proposedDestinationIndexPath.row - 1, section: proposedDestinationIndexPath.section)]\n            if previousRow is BaseInlineRowType && previousRow._inlineRow != nil {\n                return IndexPath(row: proposedDestinationIndexPath.row + (sourceIndexPath.row < proposedDestinationIndexPath.row ? 1 : -1), section:sourceIndexPath.section)\n            }\n        }\n        if section.multivaluedOptions.contains(.Insert) && proposedDestinationIndexPath.row == section.count - 1 {\n            return IndexPath(row: section.count - 2, section: sourceIndexPath.section)\n        }\n        return proposedDestinationIndexPath\n    }\n\n    open func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {\n\n        guard var section = form[sourceIndexPath.section] as? BaseMultivaluedSection else { return }\n        if sourceIndexPath.row < section.count && destinationIndexPath.row < section.count && sourceIndexPath.row != destinationIndexPath.row {\n\n            let sourceRow = form[sourceIndexPath]\n            animateTableView = false\n            section.remove(at: sourceIndexPath.row)\n            section.insert(sourceRow, at: destinationIndexPath.row)\n            animateTableView = true\n            // update the accessory view\n            let _ = inputAccessoryView(for: sourceRow)\n        }\n    }\n\n    open func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {\n        guard let section = form[indexPath.section] as? BaseMultivaluedSection else {\n\t\t\tif form[indexPath].trailingSwipe.actions.count > 0 {\n\t\t\t\treturn .delete\n\t\t\t}\n            return .none\n        }\n        if section.multivaluedOptions.contains(.Insert) && indexPath.row == section.count - 1 {\n            return section.showInsertIconInAddButton ? .insert : .none\n        }\n        if section.multivaluedOptions.contains(.Delete) {\n            return .delete\n        }\n        return .none\n    }\n\n    open func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {\n        return self.tableView(tableView, editingStyleForRowAt: indexPath) != .none\n    }\n\n\t@available(iOS 11,*)\n\topen func tableView(_ tableView: UITableView, leadingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {\n        guard !form[indexPath].leadingSwipe.actions.isEmpty else {\n            return nil\n        }\n\t\treturn form[indexPath].leadingSwipe.contextualConfiguration\n\t}\n\n\t@available(iOS 11,*)\n\topen func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {\n        guard !form[indexPath].trailingSwipe.actions.isEmpty else {\n            return nil\n        }\n\t\treturn form[indexPath].trailingSwipe.contextualConfiguration\n\t}\n\n    @available(macCatalyst, deprecated: 13.1, message: \"UITableViewRowAction is deprecated, use leading/trailingSwipe actions instead\")\n    @available(iOS, deprecated: 13, message: \"UITableViewRowAction is deprecated, use leading/trailingSwipe actions instead\")\n\topen func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?{\n        guard let actions = form[indexPath].trailingSwipe.contextualActions as? [UITableViewRowAction], !actions.isEmpty else {\n            return nil\n        }\n        return actions\n\t}\n}\n\nextension FormViewController : UITableViewDataSource {\n\n    // MARK: UITableViewDataSource\n\n    open func numberOfSections(in tableView: UITableView) -> Int {\n        return form.count\n    }\n\n    open func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {\n        return form[section].count\n    }\n\n    open func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {\n    \tform[indexPath].updateCell()\n        return form[indexPath].baseCell\n    }\n\n    open func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {\n        return form[section].header?.title\n    }\n\n    open func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {\n        return form[section].footer?.title\n    }\n\n\n    open func sectionIndexTitles(for tableView: UITableView) -> [String]? {\n        return nil\n    }\n\n    open func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {\n        return 0\n    }\n}\n\n\nextension FormViewController : UIScrollViewDelegate {\n\n    // MARK: UIScrollViewDelegate\n\n    open func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {\n        guard let tableView = tableView, scrollView === tableView else { return }\n        tableView.endEditing(true)\n    }\n}\n\nextension FormViewController {\n\n    // MARK: KeyBoard Notifications\n\n    /**\n     Called when the keyboard will appear. Adjusts insets of the tableView and scrolls it if necessary.\n     */\n    @objc open func keyboardWillShow(_ notification: Notification) {\n        guard let table = tableView, let cell = table.findFirstResponder()?.formCell() else { return }\n        let keyBoardInfo = notification.userInfo!\n        let endFrame = keyBoardInfo[UIResponder.keyboardFrameEndUserInfoKey] as! NSValue\n\n        let keyBoardFrame = table.window!.convert(endFrame.cgRectValue, to: table.superview)\n        var newBottomInset = table.frame.origin.y + table.frame.size.height - keyBoardFrame.origin.y + rowKeyboardSpacing\n        if #available(iOS 11.0, *) {\n            newBottomInset = newBottomInset - tableView.safeAreaInsets.bottom\n        }\n        var tableInsets = table.contentInset\n        var scrollIndicatorInsets = table.scrollIndicatorInsets\n        oldBottomInset = oldBottomInset ?? tableInsets.bottom\n        if newBottomInset > oldBottomInset! {\n            tableInsets.bottom = newBottomInset\n            scrollIndicatorInsets.bottom = tableInsets.bottom\n            UIView.beginAnimations(nil, context: nil)\n            UIView.setAnimationDuration((keyBoardInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double))\n            UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: (keyBoardInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! Int))!)\n            table.contentInset = tableInsets\n            table.scrollIndicatorInsets = scrollIndicatorInsets\n            if let selectedRow = table.indexPath(for: cell) {\n                if ProcessInfo.processInfo.operatingSystemVersion.majorVersion == 11 {\n                    let rect = table.rectForRow(at: selectedRow)\n                    table.scrollRectToVisible(rect, animated: animateScroll)\n                } else {\n                    table.scrollToRow(at: selectedRow, at: defaultScrollPosition, animated: animateScroll)\n                }\n            }\n            UIView.commitAnimations()\n        }\n    }\n\n    /**\n     Called when the keyboard will disappear. Adjusts insets of the tableView.\n     */\n    @objc open func keyboardWillHide(_ notification: Notification) {\n        guard let table = tableView, let oldBottom = oldBottomInset else { return }\n        let keyBoardInfo = notification.userInfo!\n        var tableInsets = table.contentInset\n        var scrollIndicatorInsets = table.scrollIndicatorInsets\n        tableInsets.bottom = oldBottom\n        scrollIndicatorInsets.bottom = tableInsets.bottom\n        oldBottomInset = nil\n        UIView.beginAnimations(nil, context: nil)\n        UIView.setAnimationDuration((keyBoardInfo[UIResponder.keyboardAnimationDurationUserInfoKey] as! Double))\n        UIView.setAnimationCurve(UIView.AnimationCurve(rawValue: (keyBoardInfo[UIResponder.keyboardAnimationCurveUserInfoKey] as! Int))!)\n        table.contentInset = tableInsets\n        table.scrollIndicatorInsets = scrollIndicatorInsets\n        UIView.commitAnimations()\n    }\n}\n\npublic enum Direction { case up, down }\n\nextension FormViewController {\n\n    // MARK: Navigation Methods\n\n    @objc func navigationDone() {\n        tableView?.endEditing(true)\n    }\n\n    @objc func navigationPrevious() {\n        navigateTo(direction: .up)\n    }\n\n    @objc func navigationNext() {\n        navigateTo(direction: .down)\n    }\n\n    open override func pressesBegan(_ presses: Set<UIPress>, with event: UIPressesEvent?) {\n        var didHandleEvent = false\n        for press in presses {\n            guard let key = press.key,\n                key.keyCode == .keyboardTab,\n                !key.modifierFlags.contains(.command) else { continue }\n            if key.modifierFlags.contains(.shift) {\n                navigateTo(direction: .up)\n            } else {\n                navigateTo(direction: .down)\n            }\n            didHandleEvent = true\n        }\n\n        if !didHandleEvent {\n            // Didn't handle this key press, so pass the event to the next responder.\n            super.pressesBegan(presses, with: event)\n        }\n    }\n\n    public func navigateTo(direction: Direction) {\n        guard let currentCell = tableView?.findFirstResponder()?.formCell() else { return }\n        guard let currentIndexPath = tableView?.indexPath(for: currentCell) else { return }\n        guard let nextRow = nextRow(for: form[currentIndexPath], withDirection: direction) else { return }\n        if nextRow.baseCell.cellCanBecomeFirstResponder() {\n            tableView?.scrollToRow(at: nextRow.indexPath!, at: .none, animated: animateScroll)\n            nextRow.baseCell.cellBecomeFirstResponder(withDirection: direction)\n        }\n    }\n\n    func nextRow(for currentRow: BaseRow, withDirection direction: Direction) -> BaseRow? {\n\n        let options = navigationOptions ?? Form.defaultNavigationOptions\n        guard options.contains(.Enabled) else { return nil }\n        guard let next = direction == .down ? form.nextRow(for: currentRow) : form.previousRow(for: currentRow) else { return nil }\n        if next.isDisabled && options.contains(.StopDisabledRow) {\n            return nil\n        }\n        if !next.baseCell.cellCanBecomeFirstResponder() && !next.isDisabled && !options.contains(.SkipCanNotBecomeFirstResponderRow) {\n            return nil\n        }\n        if !next.isDisabled && next.baseCell.cellCanBecomeFirstResponder() {\n            return next\n        }\n        return nextRow(for: next, withDirection:direction)\n    }\n}\n\nextension FormViewControllerProtocol {\n\n    // MARK: Helpers\n\n    func makeRowVisible(_ row: BaseRow, destinationScrollPosition: UITableView.ScrollPosition? = .bottom) {\n\tguard let destinationScrollPosition = destinationScrollPosition else { return }\n        guard let cell = row.baseCell, let indexPath = row.indexPath, let tableView = tableView else { return }\n        if cell.window == nil || (tableView.contentOffset.y + tableView.frame.size.height <= cell.frame.origin.y + cell.frame.size.height) {\n            tableView.scrollToRow(at: indexPath, at: destinationScrollPosition, animated: true)\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Core/Form.swift",
    "content": "//  Form.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\n/// The delegate of the Eureka form.\npublic protocol FormDelegate : AnyObject {\n    func sectionsHaveBeenAdded(_ sections: [Section], at: IndexSet)\n    func sectionsHaveBeenRemoved(_ sections: [Section], at: IndexSet)\n    func sectionsHaveBeenReplaced(oldSections: [Section], newSections: [Section], at: IndexSet)\n    func rowsHaveBeenAdded(_ rows: [BaseRow], at: [IndexPath])\n    func rowsHaveBeenRemoved(_ rows: [BaseRow], at: [IndexPath])\n    func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at: [IndexPath])\n    func valueHasBeenChanged(for row: BaseRow, oldValue: Any?, newValue: Any?)\n}\n\n// MARK: Form\n\n/// The class representing the Eureka form.\npublic final class Form {\n\n    /// Defines the default options of the navigation accessory view.\n    public static var defaultNavigationOptions = RowNavigationOptions.Enabled.union(.SkipCanNotBecomeFirstResponderRow)\n\n    /// The default options that define when an inline row will be hidden. Applies only when `inlineRowHideOptions` is nil.\n    public static var defaultInlineRowHideOptions = InlineRowHideOptions.FirstResponderChanges.union(.AnotherInlineRowIsShown)\n\n    /// The options that define when an inline row will be hidden. If nil then `defaultInlineRowHideOptions` are used\n    public var inlineRowHideOptions: InlineRowHideOptions?\n\n    /// Which `UIReturnKeyType` should be used by default. Applies only when `keyboardReturnType` is nil.\n    public static var defaultKeyboardReturnType = KeyboardReturnTypeConfiguration()\n\n    /// Which `UIReturnKeyType` should be used in this form. If nil then `defaultKeyboardReturnType` is used\n    public var keyboardReturnType: KeyboardReturnTypeConfiguration?\n\n    /// This form's delegate\n    public weak var delegate: FormDelegate?\n\n    public init() {}\n\n    /**\n     Returns the row at the given indexPath\n     */\n    public subscript(indexPath: IndexPath) -> BaseRow {\n        return self[indexPath.section][indexPath.row]\n    }\n\n    /**\n     Returns the row whose tag is passed as parameter. Uses a dictionary to get the row faster\n     */\n    public func rowBy<T>(tag: String) -> RowOf<T>? where T: Equatable{\n        let row: BaseRow? = rowBy(tag: tag)\n        return row as? RowOf<T>\n    }\n\n    /**\n     Returns the row whose tag is passed as parameter. Uses a dictionary to get the row faster\n     */\n    public func rowBy<Row>(tag: String) -> Row? where Row: RowType{\n        let row: BaseRow? = rowBy(tag: tag)\n        return row as? Row\n    }\n\n    /**\n     Returns the row whose tag is passed as parameter. Uses a dictionary to get the row faster\n     */\n    public func rowBy(tag: String) -> BaseRow? {\n        return rowsByTag[tag]\n    }\n\n    /**\n     Returns the section whose tag is passed as parameter.\n     */\n    public func sectionBy(tag: String) -> Section? {\n        return kvoWrapper._allSections.filter({ $0.tag == tag }).first\n    }\n\n    /**\n     Method used to get all the values of all the rows of the form. Only rows with tag are included.\n\n     - parameter includeHidden: If the values of hidden rows should be included.\n\n     - returns: A dictionary mapping the rows tag to its value. [tag: value]\n     */\n    public func values(includeHidden: Bool = false) -> [String: Any?] {\n        if includeHidden {\n            return getValues(for: allRows.filter({ $0.tag != nil }))\n                .merging(getValues(for: allSections.filter({ $0 is BaseMultivaluedSection && $0.tag != nil }) as? [BaseMultivaluedSection]), uniquingKeysWith: {(_, new) in new })\n        }\n        return getValues(for: rows.filter({ $0.tag != nil }))\n            .merging(getValues(for: allSections.filter({ $0 is BaseMultivaluedSection && $0.tag != nil }) as? [BaseMultivaluedSection]), uniquingKeysWith: {(_, new) in new })\n    }\n\n    /**\n     Set values to the rows of this form\n\n     - parameter values: A dictionary mapping tag to value of the rows to be set. [tag: value]\n     */\n    public func setValues(_ values: [String: Any?]) {\n        for (key, value) in values {\n            let row: BaseRow? = rowBy(tag: key)\n            row?.baseValue = value\n        }\n    }\n\n    /// The visible rows of this form\n    public var rows: [BaseRow] { return flatMap { $0 } }\n\n    /// All the rows of this form. Includes the hidden rows.\n    public var allRows: [BaseRow] { return kvoWrapper._allSections.map({ $0.kvoWrapper._allRows }).flatMap { $0 } }\n\n    /// All the sections of this form. Includes hidden sections.\n    public var allSections: [Section] { return kvoWrapper._allSections }\n\n    /**\n     * Hides all the inline rows of this form.\n     */\n    public func hideInlineRows() {\n        for row in self.allRows {\n            if let inlineRow = row as? BaseInlineRowType {\n                inlineRow.collapseInlineRow()\n            }\n        }\n    }\n\n    // MARK: Private\n\n    var rowObservers = [String: [ConditionType: [Taggable]]]()\n    var rowsByTag = [String: BaseRow]()\n    var tagToValues = [String: Any]()\n    lazy var kvoWrapper: KVOWrapper = { [unowned self] in return KVOWrapper(form: self) }()\n}\n\nextension Form: Collection {\n    public var startIndex: Int { return 0 }\n    public var endIndex: Int { return kvoWrapper.sections.count }\n}\n\nextension Form: MutableCollection {\n\n    // MARK: MutableCollectionType\n\n    public subscript (_ position: Int) -> Section {\n        get { return kvoWrapper.sections[position] as! Section }\n        set {\n            if position > kvoWrapper.sections.count {\n                assertionFailure(\"Form: Index out of bounds\")\n            }\n\n            if position < kvoWrapper.sections.count {\n                let oldSection = kvoWrapper.sections[position]\n                let oldSectionIndex = kvoWrapper._allSections.firstIndex(of: oldSection as! Section)!\n                // Remove the previous section from the form\n                kvoWrapper._allSections[oldSectionIndex].willBeRemovedFromForm()\n                kvoWrapper._allSections[oldSectionIndex] = newValue\n            } else {\n                kvoWrapper._allSections.append(newValue)\n            }\n\n            kvoWrapper.sections[position] = newValue\n            newValue.wasAddedTo(form: self)\n        }\n    }\n    public func index(after i: Int) -> Int {\n        return i+1 <= endIndex ? i+1 : endIndex\n    }\n    public func index(before i: Int) -> Int {\n        return i > startIndex ? i-1 : startIndex\n    }\n    public var last: Section? {\n        return reversed().first\n    }\n\n}\n\nextension Form : RangeReplaceableCollection {\n\n    // MARK: RangeReplaceableCollectionType\n\n    public func append(_ formSection: Section) {\n        kvoWrapper.sections.insert(formSection, at: kvoWrapper.sections.count)\n        kvoWrapper._allSections.append(formSection)\n        formSection.wasAddedTo(form: self)\n    }\n\n    public func append<S: Sequence>(contentsOf newElements: S) where S.Iterator.Element == Section {\n        kvoWrapper.sections.addObjects(from: newElements.map { $0 })\n        kvoWrapper._allSections.append(contentsOf: newElements)\n        for section in newElements {\n            section.wasAddedTo(form: self)\n        }\n    }\n\n    public func replaceSubrange<C: Collection>(\n        _ subRange: Range<Int>,\n        with newElements: C\n    ) where C.Iterator.Element == Section {\n        for i in subRange.lowerBound..<subRange.upperBound {\n            if let section = kvoWrapper.sections.object(at: i) as? Section {\n                section.willBeRemovedFromForm()\n                kvoWrapper._allSections.remove(at: kvoWrapper._allSections.firstIndex(of: section)!)\n            }\n        }\n        kvoWrapper.sections.replaceObjects(\n            in: NSRange(location: subRange.lowerBound, length: subRange.upperBound - subRange.lowerBound),\n            withObjectsFrom: newElements.map { $0 }\n        )\n        kvoWrapper._allSections.insert(contentsOf: newElements, at: indexForInsertion(at: subRange.lowerBound))\n\n        for section in newElements {\n            section.wasAddedTo(form: self)\n        }\n    }\n\n    public func replaceSubrangeInAllSections<C: Collection>(\n        _ subRange: Range<Int>,\n        with newElements: C\n    ) where C.Iterator.Element == Section {\n        // Remove subrange in all sections\n        for i in subRange.reversed() where kvoWrapper._allSections.count > i {\n            let removed = kvoWrapper._allSections.remove(at: i)\n            removed.willBeRemovedFromForm()\n        }\n\n        kvoWrapper._allSections.insert(contentsOf: newElements, at: indexForInsertion(at: subRange.lowerBound))\n\n        // Replace all visible sections by `kvoWrapper._allSections`, as hidden ones are being removed later anyway\n        kvoWrapper.sections.replaceObjects(\n            in: NSRange(location: 0, length: kvoWrapper.sections.count),\n            withObjectsFrom: kvoWrapper._allSections\n        )\n\n        for section in newElements {\n            section.wasAddedTo(form: self)\n        }\n    }\n\n    public func removeAll(keepingCapacity keepCapacity: Bool = false) {\n        // not doing anything with capacity\n\n        let sections = kvoWrapper._allSections\n        kvoWrapper.removeAllSections()\n\n        for section in sections {\n            section.willBeRemovedFromForm()\n        }\n    }\n\n    public func removeAll(where shouldBeRemoved: (Section) throws -> Bool) rethrows {\n        let indices = try kvoWrapper._allSections.enumerated()\n            .filter { try shouldBeRemoved($0.element)}\n            .map { $0.offset }\n\n        var removedSections = [Section]()\n        for index in indices.reversed() {\n            removedSections.append(kvoWrapper._allSections.remove(at: index))\n        }\n        kvoWrapper.sections.removeObjects(in: removedSections)\n\n        removedSections.forEach { $0.willBeRemovedFromForm() }\n    }\n\n    private func indexForInsertion(at index: Int) -> Int {\n        guard index != 0 else { return 0 }\n\n        let section = kvoWrapper.sections[index-1]\n        if let i = kvoWrapper._allSections.firstIndex(of: section as! Section) {\n            return i + 1\n        }\n        return kvoWrapper._allSections.count\n    }\n\n}\n\nextension Form {\n\n    // MARK: Private Helpers\n\n    class KVOWrapper: NSObject {\n        @objc dynamic private var _sections = NSMutableArray()\n        var sections: NSMutableArray { return mutableArrayValue(forKey: \"_sections\") }\n        var _allSections = [Section]()\n        private weak var form: Form?\n\n        init(form: Form) {\n            self.form = form\n            super.init()\n            addObserver(self, forKeyPath: \"_sections\", options: [.new, .old], context:nil)\n        }\n\n        deinit {\n            removeObserver(self, forKeyPath: \"_sections\")\n            _sections.removeAllObjects()\n            _allSections.removeAll()\n        }\n\n        func removeAllSections() {\n            _sections = []\n            _allSections.removeAll()\n        }\n\n        public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n            let newSections = change?[NSKeyValueChangeKey.newKey] as? [Section] ?? []\n            let oldSections = change?[NSKeyValueChangeKey.oldKey] as? [Section] ?? []\n            guard let delegateValue = form?.delegate, let keyPathValue = keyPath, let changeType = change?[NSKeyValueChangeKey.kindKey] else { return }\n            guard keyPathValue == \"_sections\" else { return }\n            switch (changeType as! NSNumber).uintValue {\n            case NSKeyValueChange.setting.rawValue:\n                if newSections.count == 0 {\n                    let indexSet = IndexSet(integersIn: 0..<oldSections.count)\n                    delegateValue.sectionsHaveBeenRemoved(oldSections, at: indexSet)\n                } else {\n                    let indexSet = change![NSKeyValueChangeKey.indexesKey] as? IndexSet ?? IndexSet(integersIn: 0..<newSections.count)\n                    delegateValue.sectionsHaveBeenAdded(newSections, at: indexSet)\n                }\n            case NSKeyValueChange.insertion.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                delegateValue.sectionsHaveBeenAdded(newSections, at: indexSet)\n            case NSKeyValueChange.removal.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                delegateValue.sectionsHaveBeenRemoved(oldSections, at: indexSet)\n            case NSKeyValueChange.replacement.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                delegateValue.sectionsHaveBeenReplaced(oldSections: oldSections, newSections: newSections, at: indexSet)\n            default:\n                assertionFailure()\n            }\n        }\n    }\n\n    func dictionaryValuesToEvaluatePredicate() -> [String: Any] {\n        return tagToValues\n    }\n\n    func addRowObservers(to taggable: Taggable, rowTags: [String], type: ConditionType) {\n        for rowTag in rowTags {\n            if rowObservers[rowTag] == nil {\n                rowObservers[rowTag] = Dictionary()\n            }\n            if let _ = rowObservers[rowTag]?[type] {\n                if !rowObservers[rowTag]![type]!.contains(where: { $0 === taggable }) {\n                    rowObservers[rowTag]?[type]!.append(taggable)\n                }\n            } else {\n                rowObservers[rowTag]?[type] = [taggable]\n            }\n        }\n    }\n\n    func removeRowObservers(from taggable: Taggable, rowTags: [String], type: ConditionType) {\n        for rowTag in rowTags {\n            guard let arr = rowObservers[rowTag]?[type], let index = arr.firstIndex(where: { $0 === taggable }) else { continue }\n            rowObservers[rowTag]?[type]?.remove(at: index)\n            if rowObservers[rowTag]?[type]?.isEmpty == true {\n                rowObservers[rowTag] = nil\n            }\n        }\n    }\n\n    func nextRow(for row: BaseRow) -> BaseRow? {\n        let allRows = rows\n        guard let index = allRows.firstIndex(of: row) else { return nil }\n        guard index < allRows.count - 1 else { return nil }\n        return allRows[index + 1]\n    }\n\n    func previousRow(for row: BaseRow) -> BaseRow? {\n        let allRows = rows\n        guard let index = allRows.firstIndex(of: row) else { return nil }\n        guard index > 0 else { return nil }\n        return allRows[index - 1]\n    }\n\n    func hideSection(_ section: Section) {\n        kvoWrapper.sections.remove(section)\n    }\n\n    func showSection(_ section: Section) {\n        guard !kvoWrapper.sections.contains(section) else { return }\n        guard var index = kvoWrapper._allSections.firstIndex(of: section) else { return }\n        var formIndex = NSNotFound\n        while formIndex == NSNotFound && index > 0 {\n            index = index - 1\n            let previous = kvoWrapper._allSections[index]\n            formIndex = kvoWrapper.sections.index(of: previous)\n        }\n        kvoWrapper.sections.insert(section, at: formIndex == NSNotFound ? 0 : formIndex + 1 )\n    }\n\t\n\tvar containsMultivaluedSection: Bool {\n\t\treturn kvoWrapper._allSections.contains { $0 is BaseMultivaluedSection }\n\t}\n\n    func getValues(for rows: [BaseRow]) -> [String: Any?] {\n        return rows.reduce([String: Any?]()) {\n            var result = $0\n            result[$1.tag!] = $1.baseValue\n            return result\n        }\n    }\n\n    func getValues(for multivaluedSections: [BaseMultivaluedSection]?) -> [String: [Any?]] {\n        return multivaluedSections?.reduce([String: [Any?]]()) {\n            var result = $0\n            result[$1.tag!] = $1.values()\n            return result\n            } ?? [:]\n    }\n\n}\n\nextension Form {\n\n    @discardableResult\n    public func validate(includeHidden: Bool = false, includeDisabled: Bool = true, quietly: Bool = false) -> [ValidationError] {\n        let rowsWithHiddenFilter = includeHidden ? allRows : rows\n        let rowsWithDisabledFilter = includeDisabled ? rowsWithHiddenFilter : rowsWithHiddenFilter.filter { $0.isDisabled != true }\n        \n        return rowsWithDisabledFilter.reduce([ValidationError]()) { res, row in\n            var res = res\n            res.append(contentsOf: row.validate(quietly: quietly))\n            return res\n        }\n    }\n    \n    // Reset rows validation\n    public func cleanValidationErrors(){\n        allRows.forEach { $0.cleanValidationErrors() }\n    }\n}\n\n"
  },
  {
    "path": "Source/Core/HeaderFooterView.swift",
    "content": "//  HeaderFooterView.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/**\n Enumeration used to generate views for the header and footer of a section.\n \n - Class:              Will generate a view of the specified class.\n - Callback->ViewType: Will generate the view as a result of the given closure.\n - NibFile:            Will load the view from a nib file.\n */\npublic enum HeaderFooterProvider<ViewType: UIView> {\n\n    /**\n     * Will generate a view of the specified class.\n     */\n    case `class`\n\n    /**\n     * Will generate the view as a result of the given closure.\n     */\n    case callback(()->ViewType)\n\n    /**\n     * Will load the view from a nib file.\n     */\n    case nibFile(name: String, bundle: Bundle?)\n\n    internal func createView() -> ViewType {\n        switch self {\n        case .class:\n            return ViewType()\n        case .callback(let builder):\n            return builder()\n        case .nibFile(let nibName, let bundle):\n            return (bundle ?? Bundle(for: ViewType.self)).loadNibNamed(nibName, owner: nil, options: nil)![0] as! ViewType\n        }\n    }\n}\n\n/**\n * Represents headers and footers of sections\n */\npublic enum HeaderFooterType {\n    case header, footer\n}\n\n/**\n *  Struct used to generate headers and footers either from a view or a String.\n */\npublic struct HeaderFooterView<ViewType: UIView> : ExpressibleByStringLiteral, HeaderFooterViewRepresentable {\n\n    /// Holds the title of the view if it was set up with a String.\n    public var title: String?\n\n    /// Generates the view.\n    public var viewProvider: HeaderFooterProvider<ViewType>?\n\n    /// Closure called when the view is created. Useful to customize its appearance.\n    public var onSetupView: ((_ view: ViewType, _ section: Section) -> Void)?\n\n    /// A closure that returns the height for the header or footer view.\n    public var height: (() -> CGFloat)?\n\n    /**\n     This method can be called to get the view corresponding to the header or footer of a section in a specific controller.\n     \n     - parameter section:    The section from which to get the view.\n     - parameter type:       Either header or footer.\n     - parameter controller: The controller from which to get that view.\n     \n     - returns: The header or footer of the specified section.\n     */\n    public func viewForSection(_ section: Section, type: HeaderFooterType) -> UIView? {\n        var view: ViewType?\n        if type == .header {\n            view = section.headerView as? ViewType ?? {\n                            let result = viewProvider?.createView()\n                            section.headerView = result\n                            return result\n                        }()\n        } else {\n            view = section.footerView as? ViewType ?? {\n                            let result = viewProvider?.createView()\n                            section.footerView = result\n                            return result\n                        }()\n        }\n        guard let v = view else { return nil }\n        onSetupView?(v, section)\n        return v\n    }\n\n    /**\n     Initiates the view with a String as title\n     */\n    public init?(title: String?) {\n        guard let t = title else { return nil }\n        self.init(stringLiteral: t)\n    }\n\n    /**\n     Initiates the view with a view provider, ideal for customized headers or footers\n     */\n    public init(_ provider: HeaderFooterProvider<ViewType>) {\n        viewProvider = provider\n    }\n\n    /**\n     Initiates the view with a String as title\n     */\n    public init(unicodeScalarLiteral value: String) {\n        self.title  = value\n    }\n\n    /**\n     Initiates the view with a String as title\n     */\n    public init(extendedGraphemeClusterLiteral value: String) {\n        self.title = value\n    }\n\n    /**\n     Initiates the view with a String as title\n     */\n    public init(stringLiteral value: String) {\n        self.title = value\n    }\n}\n\nextension UIView {\n\n    func eurekaInvalidate() {\n        setNeedsUpdateConstraints()\n        updateConstraintsIfNeeded()\n        setNeedsLayout()\n    }\n\n}\n"
  },
  {
    "path": "Source/Core/Helpers.swift",
    "content": "//  Helpers.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nextension UIView {\n\n    public func findFirstResponder() -> UIView? {\n        if isFirstResponder { return self }\n        for subView in subviews {\n            if let firstResponder = subView.findFirstResponder() {\n                return firstResponder\n            }\n        }\n        return nil\n    }\n\n    public func formCell() -> BaseCell? {\n        if self is UITableViewCell {\n            return self as? BaseCell\n        }\n        return superview?.formCell()\n    }\n}\n\nextension NSPredicate {\n\n    var predicateVars: [String] {\n        var ret = [String]()\n        if let compoundPredicate = self as? NSCompoundPredicate {\n            for subPredicate in compoundPredicate.subpredicates where subPredicate is NSPredicate {\n                ret.append(contentsOf: (subPredicate as! NSPredicate).predicateVars)\n            }\n        } else if let comparisonPredicate = self as? NSComparisonPredicate {\n            ret.append(contentsOf: comparisonPredicate.leftExpression.expressionVars)\n            ret.append(contentsOf: comparisonPredicate.rightExpression.expressionVars)\n        }\n        return ret\n    }\n}\n\nextension NSExpression {\n\n    var expressionVars: [String] {\n        switch expressionType {\n            case .function, .variable:\n                let str = \"\\(self)\"\n                if let range = str.range(of: \".\") {\n                    return [String(str[str.index(str.startIndex, offsetBy: 1)..<range.lowerBound])]\n                } else {\n                    return [String(str[str.index(str.startIndex, offsetBy: 1)...])]\n                }\n            default:\n                return []\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Core/InlineRowType.swift",
    "content": "//  InlineRowType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic protocol BaseInlineRowType {\n    /**\n     Method that can be called to expand (open) an inline row\n     */\n    func expandInlineRow()\n\n    /**\n     Method that can be called to collapse (close) an inline row\n     */\n    func collapseInlineRow()\n\n    /**\n     Method that can be called to change the status of an inline row (expanded/collapsed)\n     */\n    func toggleInlineRow()\n}\n\n/**\n *  Protocol that every inline row type has to conform to.\n */\npublic protocol InlineRowType: TypedRowType, BaseInlineRowType {\n\n    associatedtype InlineRow: BaseRow, RowType\n\n    /**\n     This function is responsible for setting up an inline row before it is first shown.\n     */\n    func setupInlineRow(_ inlineRow: InlineRow)\n}\n\nextension InlineRowType where Self: BaseRow, Self.Cell.Value ==  Self.InlineRow.Cell.Value {\n\n    /// The row that will be inserted below after the current one when it is selected.\n    public var inlineRow: Self.InlineRow? { return _inlineRow as? Self.InlineRow }\n\n    /**\n     Method that can be called to expand (open) an inline row.\n     */\n    public func expandInlineRow() {\n        if let _ = inlineRow { return }\n        if var section = section, let form = section.form {\n            let inline = InlineRow.init { _ in }\n            inline.value = value\n            inline.onChange { [weak self] in\n                self?.value = $0.value\n                self?.updateCell()\n            }\n            setupInlineRow(inline)\n            if (form.inlineRowHideOptions ?? Form.defaultInlineRowHideOptions).contains(.AnotherInlineRowIsShown) {\n                for row in form.allRows {\n                    if let inlineRow = row as? BaseInlineRowType {\n                        inlineRow.collapseInlineRow()\n                    }\n                }\n            }\n            if let onExpandInlineRowCallback = onExpandInlineRowCallback {\n                onExpandInlineRowCallback(cell, self, inline)\n            }\n            if let indexPath = indexPath {\n                _inlineRow = inline\n                section.insert(inline, at: indexPath.row + 1)\n                cell.formViewController()?.makeRowVisible(inline, destinationScrollPosition: destinationScrollPosition)\n            }\n        }\n    }\n\n    /**\n     Method that can be called to collapse (close) an inline row.\n     */\n    public func collapseInlineRow() {\n        if let selectedRowPath = indexPath, let inlineRow = _inlineRow {\n            if let onCollapseInlineRowCallback = onCollapseInlineRowCallback {\n                onCollapseInlineRowCallback(cell, self, inlineRow as! InlineRow)\n            }\n            _inlineRow = nil\n            section?.remove(at: selectedRowPath.row + 1)\n        }\n    }\n\n    /**\n     Method that can be called to change the status of an inline row (expanded/collapsed).\n     */\n    public func toggleInlineRow() {\n        if let _ = inlineRow {\n            collapseInlineRow()\n        } else {\n            expandInlineRow()\n        }\n    }\n\n    /**\n     Sets a block to be executed when a row is expanded.\n     */\n    @discardableResult\n    public func onExpandInlineRow(_ callback: @escaping (Cell, Self, InlineRow) -> Void) -> Self {\n        callbackOnExpandInlineRow = callback\n        return self\n    }\n\n    /**\n     Sets a block to be executed when a row is collapsed.\n     */\n    @discardableResult\n    public func onCollapseInlineRow(_ callback: @escaping (Cell, Self, InlineRow) -> Void) -> Self {\n        callbackOnCollapseInlineRow = callback\n        return self\n    }\n\n    /// Returns the block that will be executed when this row expands\n    public var onCollapseInlineRowCallback: ((Cell, Self, InlineRow) -> Void)? {\n        return callbackOnCollapseInlineRow as! ((Cell, Self, InlineRow) -> Void)?\n    }\n\n    /// Returns the block that will be executed when this row collapses\n    public var onExpandInlineRowCallback: ((Cell, Self, InlineRow) -> Void)? {\n        return callbackOnExpandInlineRow as! ((Cell, Self, InlineRow) -> Void)?\n    }\n\n    public var isExpanded: Bool { return _inlineRow != nil }\n    public var isCollapsed: Bool { return !isExpanded }\n}\n"
  },
  {
    "path": "Source/Core/NavigationAccessoryView.swift",
    "content": "//  NavigationAccessoryView.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\npublic protocol NavigationAccessory {\n    var doneClosure: (() -> ())? { get set }\n    var nextClosure: (() -> ())? { get set }\n    var previousClosure: (() -> ())? { get set }\n\n    var previousEnabled: Bool { get set }\n    var nextEnabled: Bool { get set }\n}\n\n/// Class for the navigation accessory view used in FormViewController\n@objc(EurekaNavigationAccessoryView)\nopen class NavigationAccessoryView: UIToolbar, NavigationAccessory {\n    open var previousButton: UIBarButtonItem!\n    open var nextButton: UIBarButtonItem!\n    open var doneButton: UIBarButtonItem!\n    private var fixedSpace = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil)\n    private var flexibleSpace = UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil)\n\n    public override init(frame: CGRect) {\n        super.init(frame: CGRect(x: 0, y: 0, width: frame.size.width, height: 44.0))\n        autoresizingMask = .flexibleWidth\n        fixedSpace.width = 22.0\n        initializeChevrons()\n        initializeDoneButton()\n        setItems([previousButton, fixedSpace, nextButton, flexibleSpace, doneButton], animated: false)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    private func drawChevron(pointingRight: Bool) -> UIImage? {\n        // Hardcoded chevron size\n        let width = 12\n        let height = 20\n\n        // Begin the image context, with which we are going to draw a chevron\n        UIGraphicsBeginImageContextWithOptions(CGSize(width: width, height: height), false, 0.0)\n        guard let context = UIGraphicsGetCurrentContext() else { return nil }\n        defer {\n            UIGraphicsEndImageContext()\n        }\n\n        // The chevron looks like > or <. This can be drawn with 3 points; the Y coordinates of the points\n        // are independant of whether it is to be pointing left or right; the X coordinates will depend, as follows.\n        // The 1s are to ensure that the point of the chevron does not sit exactly on the edge of the frame, which\n        // would slightly truncate the point.\n        let chevronPointXCoordinate, chevronTailsXCoordinate: Int\n        if pointingRight {\n            chevronPointXCoordinate = width - 1\n            chevronTailsXCoordinate = 1\n        } else {\n            chevronPointXCoordinate = 1\n            chevronTailsXCoordinate = width - 1\n        }\n\n        // Draw the lines and return the image\n        context.setLineWidth(1.5)\n        context.setLineCap(.square)\n        context.strokeLineSegments(between: [\n            CGPoint(x: chevronTailsXCoordinate, y: 0),\n            CGPoint(x: chevronPointXCoordinate, y: height / 2),\n            CGPoint(x: chevronPointXCoordinate, y: height / 2),\n            CGPoint(x: chevronTailsXCoordinate, y: height)\n        ])\n\n        return UIGraphicsGetImageFromCurrentImageContext()\n    }\n    \n    private func initializeChevrons() {\n        var imageLeftChevron, imageRightChevron: UIImage?\n        if #available(iOS 13.0, *) {\n            // If we have access to SFSymbols, use the system chevron images, rather than faffing around with our own\n            imageLeftChevron = UIImage(systemName: \"chevron.left\")\n            imageRightChevron = UIImage(systemName: \"chevron.right\")\n        } else {\n            imageLeftChevron = drawChevron(pointingRight: false)\n            imageRightChevron = drawChevron(pointingRight: true)\n        }\n        \n        // RTL language support\n        imageLeftChevron = imageLeftChevron?.imageFlippedForRightToLeftLayoutDirection()\n        imageRightChevron = imageRightChevron?.imageFlippedForRightToLeftLayoutDirection()\n\n        previousButton = UIBarButtonItem(image: imageLeftChevron, style: .plain, target: self, action: #selector(didTapPrevious))\n        nextButton = UIBarButtonItem(image: imageRightChevron, style: .plain, target: self, action: #selector(didTapNext))\n    }\n    \n    private func initializeDoneButton() {\n        doneButton = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(didTapDone))\n    }\n\n    open override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {}\n\n    public var doneClosure: (() -> ())?\n    public var nextClosure: (() -> ())?\n    public var previousClosure: (() -> ())?\n\n    @objc private func didTapDone() {\n        doneClosure?()\n    }\n\n    @objc private func didTapNext() {\n        nextClosure?()\n    }\n\n    @objc private func didTapPrevious() {\n        previousClosure?()\n    }\n\n    public var previousEnabled: Bool {\n        get {\n            return previousButton.isEnabled\n        }\n        set {\n            previousButton.isEnabled = newValue\n        }\n    }\n\n    public var nextEnabled: Bool {\n        get {\n            return nextButton.isEnabled\n        }\n        set {\n            nextButton.isEnabled = newValue\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Core/Operators.swift",
    "content": "//  Operators.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\n// MARK: Operators\n\nprecedencegroup FormPrecedence {\n    associativity: left\n    higherThan: LogicalConjunctionPrecedence\n}\n\nprecedencegroup SectionPrecedence {\n    associativity: left\n    higherThan: FormPrecedence\n}\n\ninfix operator +++ : FormPrecedence\n\n/**\n Appends a section to a form\n \n - parameter left:  the form\n - parameter right: the section to be appended\n \n - returns: the updated form\n */\n@discardableResult\npublic func +++ (left: Form, right: Section) -> Form {\n    left.append(right)\n    return left\n}\n\n/**\n Appends a section to a form\n \n - parameter left:  the form\n - parameter right: the section to be appended\n \n - returns: the updated form\n */\n#if swift(>=5.4)\n@discardableResult\npublic func +++ (left: Form, @SectionBuilder right: () -> Section) -> Form {\n    left +++ right()\n}\n#endif\n\n/**\n Appends a row to the last section of a form\n \n - parameter left:  the form\n - parameter right: the row\n */\n@discardableResult\npublic func +++ (left: Form, right: BaseRow) -> Form {\n    let section = Section()\n    let _ =  left +++ section <<< right\n    return left\n}\n\n/**\n Creates a form with two sections\n \n - parameter left:  the first section\n - parameter right: the second section\n \n - returns: the created form\n */\n@discardableResult\npublic func +++ (left: Section, right: Section) -> Form {\n    let form = Form()\n    let _ =  form +++ left +++ right\n    return form\n}\n\n/**\n Creates a form with two sections\n \n - parameter left:  the first section\n - parameter right: the second section\n \n - returns: the created form\n */\n#if swift(>=5.4)\n@discardableResult\npublic func +++ (left: Section, @SectionBuilder right: () -> Section) -> Form {\n    left +++ right()\n}\n#endif\n\n/**\n Appends the row wrapped in a new section\n \n - parameter left: a section of the form\n - parameter right: a row to be appended\n \n - returns: the form\n */\n@discardableResult\npublic func +++ (left: Section, right: BaseRow) -> Form {\n    let section = Section()\n    section <<< right\n    return left +++ section\n}\n\n/**\n Creates a form with two sections, each containing one row.\n \n - parameter left:  The row for the first section\n - parameter right: The row for the second section\n \n - returns: the created form\n */\n@discardableResult\npublic func +++ (left: BaseRow, right: BaseRow) -> Form {\n    let form = Section() <<< left +++ Section() <<< right\n    return form\n}\n\ninfix operator <<< : SectionPrecedence\n\n/**\n Appends a row to a section.\n \n - parameter left:  the section\n - parameter right: the row to be appended\n \n - returns: the section\n */\n@discardableResult\npublic func <<< (left: Section, right: BaseRow) -> Section {\n    left.append(right)\n    return left\n}\n\n/**\n Creates a section with two rows\n \n - parameter left:  The first row\n - parameter right: The second row\n \n - returns: the created section\n */\n@discardableResult\npublic func <<< (left: BaseRow, right: BaseRow) -> Section {\n    let section = Section()\n    section <<< left <<< right\n    return section\n}\n\n/**\n Appends a collection of rows to a section\n \n - parameter lhs: the section\n - parameter rhs: the rows to be appended\n */\npublic func += <C: Collection>(lhs: inout Section, rhs: C) where C.Iterator.Element == BaseRow {\n    lhs.append(contentsOf: rhs)\n}\n\n/**\n Appends a collection of section to a form\n \n - parameter lhs: the form\n - parameter rhs: the sections to be appended\n */\npublic func += <C: Collection>(lhs: inout Form, rhs: C) where C.Iterator.Element == Section {\n    lhs.append(contentsOf: rhs)\n}\n"
  },
  {
    "path": "Source/Core/PresenterRowType.swift",
    "content": "//  PresenterRowType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/**\n *  Protocol that every row that displays a new view controller must conform to.\n *  This includes presenting or pushing view controllers.\n */\npublic protocol PresenterRowType: TypedRowType {\n\n    associatedtype PresentedControllerType : UIViewController, TypedRowControllerType\n\n    /// Defines how the view controller will be presented, pushed, etc.\n    var presentationMode: PresentationMode<PresentedControllerType>? { get set }\n\n    /// Will be called before the presentation occurs.\n    var onPresentCallback: ((FormViewController, PresentedControllerType) -> Void)? { get set }\n}\n\nextension PresenterRowType {\n\n    /**\n     Sets a block to be executed when the row presents a view controller\n     \n     - parameter callback: the block\n     \n     - returns: this row\n     */\n    @discardableResult\n    public func onPresent(_ callback: ((FormViewController, PresentedControllerType) -> Void)?) -> Self {\n        onPresentCallback = callback\n        return self\n    }\n}\n"
  },
  {
    "path": "Source/Core/ResultBuilders.swift",
    "content": "//  ResultBuilders.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2022 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\n#if swift(>=5.4)\npublic protocol RowsProvider {\n    var rows: [BaseRow] { get }\n}\n\nextension BaseRow: RowsProvider {\n    public var rows: [BaseRow] { [self] }\n}\n\nextension Array: RowsProvider where Element == BaseRow {\n    public var rows: [BaseRow] { self }\n}\n\npublic protocol SectionsProvider {\n    var sections: [Section] { get }\n}\n\nextension Section: SectionsProvider {\n    public var sections: [Section] { [self] }\n}\n\nextension Array: SectionsProvider where Element == Section {\n    public var sections: [Section] { self }\n}\n\nextension BaseRow: SectionsProvider {\n    public var sections: [Section] { [.init([self])] }\n}\n\n@resultBuilder\npublic struct SectionBuilder {\n    public static func buildBlock(_ components: RowsProvider...) -> [BaseRow] {\n        components.flatMap { $0.rows }\n    }\n\n    public static func buildFinalResult(_ components: [BaseRow]) -> Section {\n        .init(components)\n    }\n    \n    public static func buildEither(first components: [RowsProvider]) -> [BaseRow] {\n        components.flatMap { $0.rows }\n    }\n    \n    public static func buildEither(second components: [RowsProvider]) -> [BaseRow] {\n        components.flatMap { $0.rows }\n    }\n\n    public static func buildOptional(_ components: [RowsProvider]?) -> [BaseRow] {\n        components?.flatMap { $0.rows } ?? []\n    }\n    \n    public static func buildExpression(_ expression: RowsProvider?) -> [BaseRow] {\n        expression.flatMap { $0.rows } ?? []\n    }\n}\n\n@resultBuilder\npublic struct FormBuilder {\n    public static func buildBlock(_ components: SectionsProvider...) -> [Section] {\n        components.flatMap { $0.sections }\n    }\n    \n    public static func buildFinalResult(_ components: [Section]) -> Form {\n        .init(components)\n    }\n    \n    public static func buildEither(first components: [SectionsProvider]) -> [Section] {\n        components.flatMap { $0.sections }\n    }\n    \n    public static func buildEither(second components: [SectionsProvider]) -> [Section] {\n        components.flatMap { $0.sections }\n    }\n    \n    public static func buildOptional(_ components: [SectionsProvider]?) -> [Section] {\n        components?.flatMap { $0.sections } ?? []\n    }\n    \n    public static func buildExpression(_ expression: SectionsProvider?) -> [Section] {\n        expression.flatMap { $0.sections } ?? []\n    }\n}\n#endif\n"
  },
  {
    "path": "Source/Core/Row.swift",
    "content": "//  Row.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\nopen class RowOf<T>: BaseRow where T: Equatable {\n\n    private var _value: T? {\n        didSet {\n            guard _value != oldValue else { return }\n            guard let form = section?.form else { return }\n            if let delegate = form.delegate {\n                delegate.valueHasBeenChanged(for: self, oldValue: oldValue, newValue: value)\n                callbackOnChange?()\n            }\n            guard let t = tag else { return }\n            form.tagToValues[t] = (value != nil ? value! : NSNull())\n            if let rowObservers = form.rowObservers[t]?[.hidden] {\n                for rowObserver in rowObservers {\n                    (rowObserver as? Hidable)?.evaluateHidden()\n                }\n            }\n            if let rowObservers = form.rowObservers[t]?[.disabled] {\n                for rowObserver in rowObservers {\n                    (rowObserver as? Disableable)?.evaluateDisabled()\n                }\n            }\n        }\n    }\n\n    /// The typed value of this row.\n    open var value: T? {\n        set (newValue) {\n            _value = newValue\n            guard let _ = section?.form else { return }\n            wasChanged = true\n            if validationOptions.contains(.validatesOnChange) || (wasBlurred && validationOptions.contains(.validatesOnChangeAfterBlurred)) ||  (!isValid && validationOptions != .validatesOnDemand) {\n                validate()\n            }\n        }\n        get {\n            return _value\n        }\n    }\n    \n    /// The reset value of this row. Sets the value property to the value of this row on the resetValue method call.\n    open var resetValue: T?\n\n    /// The untyped value of this row.\n    public override var baseValue: Any? {\n        get { return value }\n        set { value = newValue as? T }\n    }\n\n    /// Block variable used to get the String that should be displayed for the value of this row.\n    public var displayValueFor: ((T?) -> String?)? = {\n        return $0.map { String(describing: $0) }\n    }\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    public internal(set) var rules: [ValidationRuleHelper<T>] = []\n\n    @discardableResult\n    open override func validate(quietly: Bool = false) -> [ValidationError] {\n        var vErrors = [ValidationError]()\n        #if swift(>=4.1)\n        vErrors = rules.compactMap { $0.validateFn(value) }\n        #else\n        vErrors = rules.flatMap { $0.validateFn(value) }\n        #endif\n        if (!quietly) {\n            validationErrors = vErrors\n        }\n        return vErrors\n    }\n    \n    /// Resets the value of the row. Setting it's value to it's reset value.\n    public func resetRowValue() {\n        value = resetValue\n    }\n\n    /// Add a Validation rule for the Row\n    /// - Parameter rule: RuleType object to add\n    public func add<Rule: RuleType>(rule: Rule) where T == Rule.RowValueType {\n        let validFn: ((T?) -> ValidationError?) = { (val: T?) in\n            return rule.isValid(value: val)\n        }\n        rules.append(ValidationRuleHelper(validateFn: validFn, rule: rule))\n    }\n\n    /// Add a Validation rule set for the Row\n    /// - Parameter ruleSet: RuleSet<T> set of rules to add\n    public func add(ruleSet: RuleSet<T>) {\n        rules.append(contentsOf: ruleSet.rules)\n    }\n\n    public func remove(ruleWithIdentifier identifier: String) {\n        if let index = rules.firstIndex(where: { (validationRuleHelper) -> Bool in\n            return validationRuleHelper.rule.id == identifier\n        }) {\n            rules.remove(at: index)\n        }\n    }\n\n    public func removeAllRules() {\n        validationErrors.removeAll()\n        rules.removeAll()\n    }\n\n}\n\n/// Generic class that represents an Eureka row.\nopen class Row<Cell: CellType>: RowOf<Cell.Value>, TypedRowType where Cell: BaseCell {\n\n    /// Responsible for creating the cell for this row.\n    public var cellProvider = CellProvider<Cell>()\n\n    /// The type of the cell associated to this row.\n    public let cellType: Cell.Type! = Cell.self\n\n    private var _cell: Cell! {\n        didSet {\n            RowDefaults.cellSetup[\"\\(type(of: self))\"]?(_cell, self)\n            (callbackCellSetup as? ((Cell) -> Void))?(_cell)\n        }\n    }\n\n    /// The cell associated to this row.\n    public var cell: Cell! {\n        return _cell ?? {\n            let result = cellProvider.makeCell(style: self.cellStyle)\n            result.row = self\n            result.setup()\n            _cell = result\n            return _cell\n        }()\n    }\n\n    /// The untyped cell associated to this row\n    public override var baseCell: BaseCell { return cell }\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    /**\n     Method that reloads the cell\n     */\n    override open func updateCell() {\n        super.updateCell()\n        cell.update()\n        customUpdateCell()\n        RowDefaults.cellUpdate[\"\\(type(of: self))\"]?(cell, self)\n        callbackCellUpdate?()\n    }\n\n    /**\n     Method called when the cell belonging to this row was selected. Must call the corresponding method in its cell.\n     */\n    open override func didSelect() {\n        super.didSelect()\n        if !isDisabled {\n            cell?.didSelect()\n        }\n        customDidSelect()\n        callbackCellOnSelection?()\n    }\n\n    /**\n     Will be called inside `didSelect` method of the row. Can be used to customize row selection from the definition of the row.\n     */\n    open func customDidSelect() {}\n\n    /**\n     Will be called inside `updateCell` method of the row. Can be used to customize reloading a row from its definition.\n     */\n    open func customUpdateCell() {}\n\n}\n"
  },
  {
    "path": "Source/Core/RowControllerType.swift",
    "content": "//  RowControllerType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/**\n *  Base protocol for view controllers presented by Eureka rows.\n */\npublic protocol RowControllerType: NSObjectProtocol {\n\n    /// A closure to be called when the controller disappears.\n    var onDismissCallback: ((UIViewController) -> Void)? { get set }\n}\n"
  },
  {
    "path": "Source/Core/RowProtocols.swift",
    "content": "//  RowProtocols.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/**\n *  Protocol that view controllers pushed or presented by a row should conform to.\n */\npublic protocol TypedRowControllerType: RowControllerType {\n    associatedtype RowValue: Equatable\n\n    /// The row that pushed or presented this controller\n    var row: RowOf<Self.RowValue>! { get set }\n}\n\n// MARK: Header Footer Protocols\n\n/**\n *  Protocol used to set headers and footers to sections.\n *  Can be set with a view or a String\n */\npublic protocol HeaderFooterViewRepresentable {\n\n    /**\n     This method can be called to get the view corresponding to the header or footer of a section in a specific controller.\n     \n     - parameter section:    The section from which to get the view.\n     - parameter type:       Either header or footer.\n     - parameter controller: The controller from which to get that view.\n     \n     - returns: The header or footer of the specified section.\n     */\n    func viewForSection(_ section: Section, type: HeaderFooterType) -> UIView?\n\n    /// If the header or footer of a section was created with a String then it will be stored in the title.\n    var title: String? { get set }\n\n    /// The height of the header or footer.\n    var height: (() -> CGFloat)? { get set }\n}\n"
  },
  {
    "path": "Source/Core/RowType.swift",
    "content": "//  RowType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nprotocol Disableable: Taggable {\n    func evaluateDisabled()\n    var disabled: Condition? { get set }\n    var isDisabled: Bool { get }\n}\n\nprotocol Hidable: Taggable {\n    func evaluateHidden()\n    var hidden: Condition? { get set }\n    var isHidden: Bool { get }\n}\n\npublic protocol KeyboardReturnHandler: BaseRowType {\n    var keyboardReturnType: KeyboardReturnTypeConfiguration? { get set }\n}\n\npublic protocol Taggable: AnyObject {\n    var tag: String? { get set }\n}\n\npublic protocol BaseRowType: Taggable {\n\n    /// The cell associated to this row.\n    var baseCell: BaseCell! { get }\n\n    /// The section to which this row belongs.\n    var section: Section? { get }\n\n    /// Parameter used when creating the cell for this row.\n    var cellStyle: UITableViewCell.CellStyle { get set }\n\n    /// The title will be displayed in the textLabel of the row.\n    var title: String? { get set }\n\n    /**\n     Method that should re-display the cell\n     */\n    func updateCell()\n\n    /**\n     Method called when the cell belonging to this row was selected. Must call the corresponding method in its cell.\n     */\n    func didSelect()\n\n    /**\n     Typically we don't need to explicitly call this method since it is called by Eureka framework. It will validates the row if you invoke it.\n     */\n    func validate(quietly: Bool) -> [ValidationError]\n}\n\npublic protocol TypedRowType: BaseRowType {\n\n    associatedtype Cell: BaseCell, TypedCellType\n\n    /// The typed cell associated to this row.\n    var cell: Cell! { get }\n\n    /// The typed value this row stores.\n    var value: Cell.Value? { get set }\n\n    func add<Rule: RuleType>(rule: Rule) where Rule.RowValueType == Cell.Value\n    func remove(ruleWithIdentifier: String)\n}\n\n/**\n *  Protocol that every row type has to conform to.\n */\npublic protocol RowType: TypedRowType {\n    init(_ tag: String?, _ initializer: (Self) -> Void)\n}\n\nextension RowType where Self: BaseRow {\n\n    /**\n     Default initializer for a row\n     */\n    public init(_ tag: String? = nil, _ initializer: (Self) -> Void = { _ in }) {\n        self.init(tag: tag)\n        RowDefaults.rowInitialization[\"\\(type(of: self))\"]?(self)\n        initializer(self)\n    }\n}\n\nextension RowType where Self: BaseRow {\n\n    /// The default block executed when the cell is updated. Applies to every row of this type.\n    public static var defaultCellUpdate: ((Cell, Self) -> Void)? {\n        set {\n            if let newValue = newValue {\n                let wrapper: (BaseCell, BaseRow) -> Void = { (baseCell: BaseCell, baseRow: BaseRow) in\n                    newValue(baseCell as! Cell, baseRow as! Self)\n                }\n                RowDefaults.cellUpdate[\"\\(self)\"] = wrapper\n                RowDefaults.rawCellUpdate[\"\\(self)\"] = newValue\n            } else {\n                RowDefaults.cellUpdate[\"\\(self)\"] = nil\n                RowDefaults.rawCellUpdate[\"\\(self)\"] = nil\n            }\n        }\n        get { return RowDefaults.rawCellUpdate[\"\\(self)\"] as? ((Cell, Self) -> Void) }\n    }\n\n    /// The default block executed when the cell is created. Applies to every row of this type.\n    public static var defaultCellSetup: ((Cell, Self) -> Void)? {\n        set {\n            if let newValue = newValue {\n                let wrapper: (BaseCell, BaseRow) -> Void = { (baseCell: BaseCell, baseRow: BaseRow) in\n                    newValue(baseCell as! Cell, baseRow as! Self)\n                }\n                RowDefaults.cellSetup[\"\\(self)\"] = wrapper\n                RowDefaults.rawCellSetup[\"\\(self)\"] = newValue\n            } else {\n                RowDefaults.cellSetup[\"\\(self)\"] = nil\n                RowDefaults.rawCellSetup[\"\\(self)\"] = nil\n            }\n        }\n        get { return RowDefaults.rawCellSetup[\"\\(self)\"] as? ((Cell, Self) -> Void) }\n    }\n\n    /// The default block executed when the cell becomes first responder. Applies to every row of this type.\n    public static var defaultOnCellHighlightChanged: ((Cell, Self) -> Void)? {\n        set {\n            if let newValue = newValue {\n                let wrapper: (BaseCell, BaseRow) -> Void = { (baseCell: BaseCell, baseRow: BaseRow) in\n                    newValue(baseCell as! Cell, baseRow as! Self)\n                }\n                RowDefaults.onCellHighlightChanged [\"\\(self)\"] = wrapper\n                RowDefaults.rawOnCellHighlightChanged[\"\\(self)\"] = newValue\n            } else {\n                RowDefaults.onCellHighlightChanged[\"\\(self)\"] = nil\n                RowDefaults.rawOnCellHighlightChanged[\"\\(self)\"] = nil\n            }\n        }\n        get { return RowDefaults.rawOnCellHighlightChanged[\"\\(self)\"] as? ((Cell, Self) -> Void) }\n    }\n\n    /// The default block executed to initialize a row. Applies to every row of this type.\n    public static var defaultRowInitializer: ((Self) -> Void)? {\n        set {\n            if let newValue = newValue {\n                let wrapper: (BaseRow) -> Void = { (baseRow: BaseRow) in\n                    newValue(baseRow as! Self)\n                }\n                RowDefaults.rowInitialization[\"\\(self)\"] = wrapper\n                RowDefaults.rawRowInitialization[\"\\(self)\"] = newValue\n            } else {\n                RowDefaults.rowInitialization[\"\\(self)\"] = nil\n                RowDefaults.rawRowInitialization[\"\\(self)\"] = nil\n            }\n        }\n        get { return RowDefaults.rawRowInitialization[\"\\(self)\"] as? ((Self) -> Void) }\n    }\n\n    /// The default block executed to initialize a row. Applies to every row of this type.\n    public static var defaultOnRowValidationChanged: ((Cell, Self) -> Void)? {\n        set {\n            if let newValue = newValue {\n                let wrapper: (BaseCell, BaseRow) -> Void = { (baseCell: BaseCell, baseRow: BaseRow) in\n                    newValue(baseCell as! Cell, baseRow as! Self)\n                }\n                RowDefaults.onRowValidationChanged[\"\\(self)\"] = wrapper\n                RowDefaults.rawOnRowValidationChanged[\"\\(self)\"] = newValue\n            } else {\n                RowDefaults.onRowValidationChanged[\"\\(self)\"] = nil\n                RowDefaults.rawOnRowValidationChanged[\"\\(self)\"] = nil\n            }\n        }\n        get { return RowDefaults.rawOnRowValidationChanged[\"\\(self)\"] as? ((Cell, Self) -> Void) }\n    }\n\n    /**\n     Sets a block to be called when the value of this row changes.\n\n     - returns: this row\n     */\n    @discardableResult\n    public func onChange(_ callback: @escaping (Self) -> Void) -> Self {\n        callbackOnChange = { [weak self] in callback(self!) }\n        return self\n    }\n\n    /**\n     Sets a block to be called when the cell corresponding to this row is refreshed.\n\n     - returns: this row\n     */\n    @discardableResult\n    public func cellUpdate(_ callback: @escaping ((_ cell: Cell, _ row: Self) -> Void)) -> Self {\n        callbackCellUpdate = { [weak self] in  callback(self!.cell, self!) }\n        return self\n    }\n\n    /**\n     Sets a block to be called when the cell corresponding to this row is created.\n\n     - returns: this row\n     */\n    @discardableResult\n    public func cellSetup(_ callback: @escaping ((_ cell: Cell, _ row: Self) -> Void)) -> Self {\n        callbackCellSetup = { [weak self] (cell: Cell) in  callback(cell, self!) }\n        return self\n    }\n\n    /**\n     Sets a block to be called when the cell corresponding to this row is selected.\n\n     - returns: this row\n     */\n    @discardableResult\n    public func onCellSelection(_ callback: @escaping ((_ cell: Cell, _ row: Self) -> Void)) -> Self {\n        callbackCellOnSelection = { [weak self] in  callback(self!.cell, self!) }\n        return self\n    }\n\n    /**\n     Sets a block to be called when the cell corresponding to this row becomes or resigns the first responder.\n\n     - returns: this row\n     */\n    @discardableResult\n    public func onCellHighlightChanged(_ callback: @escaping (_ cell: Cell, _ row: Self) -> Void) -> Self {\n        callbackOnCellHighlightChanged = { [weak self] in callback(self!.cell, self!) }\n        return self\n    }\n\n    @discardableResult\n    public func onRowValidationChanged(_ callback: @escaping (_ cell: Cell, _ row: Self) -> Void) -> Self {\n        callbackOnRowValidationChanged = { [weak self] in  callback(self!.cell, self!) }\n        return self\n    }\n}\n"
  },
  {
    "path": "Source/Core/Section.swift",
    "content": "//  Section.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// The delegate of the Eureka sections.\npublic protocol SectionDelegate: AnyObject {\n    func rowsHaveBeenAdded(_ rows: [BaseRow], at: IndexSet)\n    func rowsHaveBeenRemoved(_ rows: [BaseRow], at: IndexSet)\n    func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at: IndexSet)\n}\n\n// MARK: Section\n\nextension Section : Equatable {}\n\npublic func == (lhs: Section, rhs: Section) -> Bool {\n    return lhs === rhs\n}\n\nextension Section : Hidable, SectionDelegate {}\n\nextension Section {\n\n    public func reload(with rowAnimation: UITableView.RowAnimation = .none) {\n        guard let tableView = (form?.delegate as? FormViewController)?.tableView, let index = index, index < tableView.numberOfSections else { return }\n        tableView.reloadSections(IndexSet(integer: index), with: rowAnimation)\n    }\n}\n\nextension Section {\n\n    internal class KVOWrapper: NSObject {\n\n        @objc dynamic private var _rows = NSMutableArray()\n        var rows: NSMutableArray {\n            return mutableArrayValue(forKey: \"_rows\")\n        }\n        var _allRows = [BaseRow]()\n\n        private weak var section: Section?\n\n        init(section: Section) {\n            self.section = section\n            super.init()\n            addObserver(self, forKeyPath: \"_rows\", options: [.new, .old], context:nil)\n        }\n\n        deinit {\n            removeObserver(self, forKeyPath: \"_rows\")\n            _rows.removeAllObjects()\n            _allRows.removeAll()\n        }\n\n        func removeAllRows() {\n            _rows = []\n            _allRows.removeAll()\n        }\n\n        public override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n            let newRows = change![NSKeyValueChangeKey.newKey] as? [BaseRow] ?? []\n            let oldRows = change![NSKeyValueChangeKey.oldKey] as? [BaseRow] ?? []\n            guard let keyPathValue = keyPath, let changeType = change?[NSKeyValueChangeKey.kindKey] else { return }\n            let delegateValue = section?.form?.delegate\n            guard keyPathValue == \"_rows\" else { return }\n            switch (changeType as! NSNumber).uintValue {\n            case NSKeyValueChange.setting.rawValue:\n                if newRows.count == 0 {\n                    let indexSet = IndexSet(integersIn: 0..<oldRows.count)\n                    section?.rowsHaveBeenRemoved(oldRows, at: indexSet)\n                    if let _index = section?.index {\n                        delegateValue?.rowsHaveBeenRemoved(oldRows, at: (0..<oldRows.count).map { IndexPath(row: $0, section: _index) })\n                    }\n                } else {\n                    let indexSet = IndexSet(integersIn: 0..<newRows.count)\n                    section?.rowsHaveBeenAdded(newRows, at: indexSet)\n                    if let _index = section?.index {\n                        delegateValue?.rowsHaveBeenAdded(newRows, at: indexSet.map { IndexPath(row: $0, section: _index) })\n                    }\n                }\n            case NSKeyValueChange.insertion.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                section?.rowsHaveBeenAdded(newRows, at: indexSet)\n                if let _index = section?.index {\n                    delegateValue?.rowsHaveBeenAdded(newRows, at: indexSet.map { IndexPath(row: $0, section: _index ) })\n                }\n            case NSKeyValueChange.removal.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                section?.rowsHaveBeenRemoved(oldRows, at: indexSet)\n                if let _index = section?.index {\n                    delegateValue?.rowsHaveBeenRemoved(oldRows, at: indexSet.map { IndexPath(row: $0, section: _index ) })\n                }\n            case NSKeyValueChange.replacement.rawValue:\n                let indexSet = change![NSKeyValueChangeKey.indexesKey] as! IndexSet\n                section?.rowsHaveBeenReplaced(oldRows: oldRows, newRows: newRows, at: indexSet)\n                if let _index = section?.index {\n                    delegateValue?.rowsHaveBeenReplaced(oldRows: oldRows, newRows: newRows, at: indexSet.map { IndexPath(row: $0, section: _index)})\n                }\n            default:\n                assertionFailure()\n            }\n        }\n    }\n\n    /**\n     *  If this section contains a row (hidden or not) with the passed parameter as tag then that row will be returned.\n     *  If not, it returns nil.\n     */\n    public func rowBy<Row: RowType>(tag: String) -> Row? {\n        guard let index = kvoWrapper._allRows.firstIndex(where: { $0.tag == tag }) else { return nil }\n        return kvoWrapper._allRows[index] as? Row\n    }\n}\n\n/// The class representing the sections in a Eureka form.\nopen class Section {\n\n    /// The tag is used to uniquely identify a Section. Must be unique among sections and rows.\n    public var tag: String?\n\n    /// The form that contains this section\n    public internal(set) weak var form: Form?\n\n    /// The header of this section.\n    public var header: HeaderFooterViewRepresentable? {\n        willSet {\n            headerView = nil\n        }\n    }\n\n    /// The footer of this section\n    public var footer: HeaderFooterViewRepresentable? {\n        willSet {\n            footerView = nil\n        }\n    }\n\n    /// Index of this section in the form it belongs to.\n    public var index: Int? { return form?.firstIndex(of: self) }\n\n    /// Condition that determines if the section should be hidden or not.\n    public var hidden: Condition? {\n        willSet { removeFromRowObservers() }\n        didSet { addToRowObservers() }\n    }\n\n    /// Returns if the section is currently hidden or not.\n    public var isHidden: Bool { return hiddenCache }\n\n    /// Returns all the rows in this section, including hidden rows.\n    public var allRows: [BaseRow] {\n        return kvoWrapper._allRows\n    }\n\n    public required init() {}\n\n    #if swift(>=4.1)\n    public required init<S>(_ elements: S) where S: Sequence, S.Element == BaseRow {\n        self.append(contentsOf: elements)\n    }\n    #endif\n\n    public init(_ initializer: @escaping (Section) -> Void) {\n        initializer(self)\n    }\n\n    public init(_ header: String?, _ initializer: @escaping (Section) -> Void = { _ in }) {\n        if let header = header {\n            self.header = HeaderFooterView(stringLiteral: header)\n        }\n        initializer(self)\n    }\n\n    public init(header: String?, footer: String?, _ initializer: (Section) -> Void = { _ in }) {\n        if let header = header {\n            self.header = HeaderFooterView(stringLiteral: header)\n        }\n        if let footer = footer {\n            self.footer = HeaderFooterView(stringLiteral: footer)\n        }\n        initializer(self)\n    }\n\n    public init(footer: String?, _ initializer: (Section) -> Void = { _ in }) {\n        if let footer = footer {\n            self.footer = HeaderFooterView(stringLiteral: footer)\n        }\n        initializer(self)\n    }\n\n    // MARK: SectionDelegate\n\n    /**\n     *  Delegate method called by the framework when one or more rows have been added to the section.\n     */\n    open func rowsHaveBeenAdded(_ rows: [BaseRow], at: IndexSet) {}\n\n    /**\n     *  Delegate method called by the framework when one or more rows have been removed from the section.\n     */\n    open func rowsHaveBeenRemoved(_ rows: [BaseRow], at: IndexSet) {}\n\n    /**\n     *  Delegate method called by the framework when one or more rows have been replaced in the section.\n     */\n    open func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at: IndexSet) {}\n\n    // MARK: Private\n    lazy var kvoWrapper: KVOWrapper = { [unowned self] in return KVOWrapper(section: self) }()\n\n    var headerView: UIView?\n    var footerView: UIView?\n    var hiddenCache = false\n}\n\nextension Section: MutableCollection, BidirectionalCollection {\n\n    // MARK: MutableCollectionType\n\n    public var startIndex: Int { return 0 }\n    public var endIndex: Int { return kvoWrapper.rows.count }\n    public subscript (position: Int) -> BaseRow {\n        get {\n            if position >= kvoWrapper.rows.count {\n                assertionFailure(\"Section: Index out of bounds\")\n            }\n            return kvoWrapper.rows[position] as! BaseRow\n        }\n        set {\n            if position > kvoWrapper.rows.count {\n                assertionFailure(\"Section: Index out of bounds\")\n            }\n\n            if position < kvoWrapper.rows.count {\n                let oldRow = kvoWrapper.rows[position]\n                let oldRowIndex = kvoWrapper._allRows.firstIndex(of: oldRow as! BaseRow)!\n                // Remove the previous row from the form\n                kvoWrapper._allRows[oldRowIndex].willBeRemovedFromSection()\n                kvoWrapper._allRows[oldRowIndex] = newValue\n            } else {\n                kvoWrapper._allRows.append(newValue)\n            }\n\n            kvoWrapper.rows[position] = newValue\n            newValue.wasAddedTo(section: self)\n        }\n    }\n\n    public subscript (range: Range<Int>) -> ArraySlice<BaseRow> {\n        get { return kvoWrapper.rows.map { $0 as! BaseRow }[range] }\n        set { replaceSubrange(range, with: newValue) }\n    }\n\n    public func index(after i: Int) -> Int { return i + 1 }\n    public func index(before i: Int) -> Int { return i - 1 }\n\n}\n\nextension Section: RangeReplaceableCollection {\n\n    // MARK: RangeReplaceableCollectionType\n\n    public func append(_ formRow: BaseRow) {\n        kvoWrapper.rows.insert(formRow, at: kvoWrapper.rows.count)\n        kvoWrapper._allRows.append(formRow)\n        formRow.wasAddedTo(section: self)\n    }\n\n    public func append<S: Sequence>(contentsOf newElements: S) where S.Iterator.Element == BaseRow {\n        kvoWrapper.rows.addObjects(from: newElements.map { $0 })\n        kvoWrapper._allRows.append(contentsOf: newElements)\n        for row in newElements {\n            row.wasAddedTo(section: self)\n        }\n    }\n\n    public func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C) where C : Collection, C.Element == BaseRow {\n        for i in subrange.lowerBound..<subrange.upperBound {\n            if let row = kvoWrapper.rows.object(at: i) as? BaseRow {\n                row.willBeRemovedFromSection()\n                kvoWrapper._allRows.remove(at: kvoWrapper._allRows.firstIndex(of: row)!)\n            }\n        }\n\n        kvoWrapper.rows.replaceObjects(in: NSRange(location: subrange.lowerBound, length: subrange.upperBound - subrange.lowerBound),\n                                       withObjectsFrom: newElements.map { $0 })\n\n        kvoWrapper._allRows.insert(contentsOf: newElements, at: indexForInsertion(at: subrange.lowerBound))\n        for row in newElements {\n            row.wasAddedTo(section: self)\n        }\n    }\n\n    public func removeAll(keepingCapacity keepCapacity: Bool = false) {\n        // not doing anything with capacity\n\n        let rows = kvoWrapper._allRows\n        kvoWrapper.removeAllRows()\n\n        for row in rows {\n            row.willBeRemovedFromSection()\n        }\n    }\n\n    public func removeAll(where shouldBeRemoved: (BaseRow) throws -> Bool) rethrows {\n        let indices = try kvoWrapper._allRows.enumerated()\n            .filter { try shouldBeRemoved($0.element)}\n            .map { $0.offset }\n        \n        var removedRows = [BaseRow]()\n        for index in indices.reversed() {\n            removedRows.append(kvoWrapper._allRows.remove(at: index))\n        }\n        kvoWrapper.rows.removeObjects(in: removedRows)\n\n        removedRows.forEach { $0.willBeRemovedFromSection() }\n    }\n\n    @discardableResult\n    public func remove(at position: Int) -> BaseRow {\n        let row = kvoWrapper.rows.object(at: position) as! BaseRow\n        row.willBeRemovedFromSection()\n        kvoWrapper.rows.removeObject(at: position)\n        if let index = kvoWrapper._allRows.firstIndex(of: row) {\n            kvoWrapper._allRows.remove(at: index)\n        }\n\n        return row\n    }\n\n    private func indexForInsertion(at index: Int) -> Int {\n        guard index != 0 else { return 0 }\n\n        let row = kvoWrapper.rows[index-1]\n        if let i = kvoWrapper._allRows.firstIndex(of: row as! BaseRow) {\n            return i + 1\n        }\n        return kvoWrapper._allRows.count\n    }\n\n}\n\nextension Section /* Condition */ {\n\n    // MARK: Hidden/Disable Engine\n\n    /**\n     Function that evaluates if the section should be hidden and updates it accordingly.\n     */\n    public final func evaluateHidden() {\n        if let h = hidden, let f = form {\n            switch h {\n            case .function(_, let callback):\n                hiddenCache = callback(f)\n            case .predicate(let predicate):\n                hiddenCache = predicate.evaluate(with: self, substitutionVariables: f.dictionaryValuesToEvaluatePredicate())\n            }\n            if hiddenCache {\n                form?.hideSection(self)\n            } else {\n                form?.showSection(self)\n            }\n        }\n    }\n\n    /**\n     Internal function called when this section was added to a form.\n     */\n    func wasAddedTo(form: Form) {\n        self.form = form\n        addToRowObservers()\n        evaluateHidden()\n        for row in kvoWrapper._allRows {\n            row.wasAddedTo(section: self)\n        }\n    }\n\n    /**\n     Internal function called to add this section to the observers of certain rows. Called when the hidden variable is set and depends on other rows.\n     */\n    func addToRowObservers() {\n        guard let h = hidden else { return }\n        switch h {\n        case .function(let tags, _):\n            form?.addRowObservers(to: self, rowTags: tags, type: .hidden)\n        case .predicate(let predicate):\n            form?.addRowObservers(to: self, rowTags: predicate.predicateVars, type: .hidden)\n        }\n    }\n\n    /**\n     Internal function called when this section was removed from a form.\n     */\n    func willBeRemovedFromForm() {\n        for row in kvoWrapper._allRows {\n            row.willBeRemovedFromForm()\n        }\n        removeFromRowObservers()\n        self.form = nil\n    }\n\n    /**\n     Internal function called to remove this section from the observers of certain rows. Called when the hidden variable is changed.\n     */\n    func removeFromRowObservers() {\n        guard let h = hidden else { return }\n        switch h {\n        case .function(let tags, _):\n            form?.removeRowObservers(from: self, rowTags: tags, type: .hidden)\n        case .predicate(let predicate):\n            form?.removeRowObservers(from: self, rowTags: predicate.predicateVars, type: .hidden)\n        }\n    }\n\n    func hide(row: BaseRow) {\n        row.baseCell.cellResignFirstResponder()\n        (row as? BaseInlineRowType)?.collapseInlineRow()\n        kvoWrapper.rows.remove(row)\n    }\n\n    func show(row: BaseRow) {\n        guard !kvoWrapper.rows.contains(row) else { return }\n        guard var index = kvoWrapper._allRows.firstIndex(of: row) else { return }\n        var formIndex = NSNotFound\n        while formIndex == NSNotFound && index > 0 {\n            index = index - 1\n            let previous = kvoWrapper._allRows[index]\n            formIndex = kvoWrapper.rows.index(of: previous)\n        }\n        kvoWrapper.rows.insert(row, at: formIndex == NSNotFound ? 0 : formIndex + 1)\n    }\n}\n\nextension Section /* Helpers */ {\n\n    /**\n     *  This method inserts a row after another row.\n     *  It is useful if you want to insert a row after a row that is currently hidden. Otherwise use `insert(at: Int)`.\n     *  It throws an error if the old row is not in this section.\n     */\n    public func insert(row newRow: BaseRow, after previousRow: BaseRow) throws {\n        guard let rowIndex = (kvoWrapper._allRows as [BaseRow]).firstIndex(of: previousRow) else {\n            throw EurekaError.rowNotInSection(row: previousRow)\n        }\n        kvoWrapper._allRows.insert(newRow, at: index(after: rowIndex))\n        show(row: newRow)\n        newRow.wasAddedTo(section: self)\n    }\n\n}\n\n/**\n *  Navigation options for a form view controller.\n */\npublic struct MultivaluedOptions: OptionSet {\n\n    private enum Options: Int {\n        case none = 0, insert = 1, delete = 2, reorder = 4\n    }\n    public let rawValue: Int\n    public  init(rawValue: Int) { self.rawValue = rawValue}\n    private init(_ options: Options) { self.rawValue = options.rawValue }\n\n    /// No multivalued.\n    public static let None = MultivaluedOptions(.none)\n\n    /// Allows user to insert rows.\n    public static let Insert = MultivaluedOptions(.insert)\n\n    /// Allows user to delete rows.\n    public static let Delete = MultivaluedOptions(.delete)\n\n    /// Allows user to reorder rows\n    public static let Reorder = MultivaluedOptions(.reorder)\n}\n\n/// Base class for multivalued sections. Use one of the subclasses.\nopen class BaseMultivaluedSection: Section {\n    public var multivaluedOptions: MultivaluedOptions\n    public var showInsertIconInAddButton = true\n\n    public var multivaluedRowToInsertAt: ((Int) -> BaseRow)?\n\n    public required init(multivaluedOptions: MultivaluedOptions = MultivaluedOptions.Insert.union(.Delete),\n                         header: String? = nil,\n                         footer: String? = nil,\n                         _ initializer: (BaseMultivaluedSection) -> Void = { _ in }) {\n        self.multivaluedOptions = multivaluedOptions\n        super.init(header: header, footer: footer, {section in initializer(section as! BaseMultivaluedSection) })\n        guard multivaluedOptions.contains(.Insert) else { return }\n        initialize()\n    }\n\n    public required init() {\n        self.multivaluedOptions = MultivaluedOptions.Insert.union(.Delete)\n        super.init()\n        initialize()\n    }\n\n    #if swift(>=4.1)\n    public required init<S>(_ elements: S) where S : Sequence, S.Element == BaseRow {\n        self.multivaluedOptions = MultivaluedOptions.Insert.union(.Delete)\n        super.init(elements)\n        initialize()\n    }\n    #endif\n\n    func initialize() {\n        // Overridden by subclasses\n    }\n\n    /**\n     Method used to get all the values of the section.\n\n     - returns: An Array mapping the row values. [value]\n     */\n    public func values() -> [Any?] {\n        return kvoWrapper._allRows.filter({ $0.baseValue != nil }).map({ $0.baseValue })\n    }\n\n}\n\n/// Generic multivalued section. Pass the type of the add button row as generic parameter.\nopen class GenericMultivaluedSection<AddButtonType: RowType>: BaseMultivaluedSection where AddButtonType: BaseRow {\n\n    public var addButtonProvider: ((GenericMultivaluedSection<AddButtonType>) -> AddButtonType)!\n\n    public required init(multivaluedOptions: MultivaluedOptions = MultivaluedOptions.Insert.union(.Delete),\n                         header: String? = nil,\n                         footer: String? = nil,\n                         _ initializer: (GenericMultivaluedSection<AddButtonType>) -> Void = { _ in }) {\n        super.init(multivaluedOptions: multivaluedOptions, header: header, footer: footer, {section in initializer(section as! GenericMultivaluedSection<AddButtonType>) })\n    }\n\n    public required init() {\n        super.init()\n    }\n\n    #if swift(>=4.1)\n    public required init<S>(_ elements: S) where S : Sequence, S.Element == BaseRow {\n        super.init(elements)\n    }\n    #endif\n\n    override func initialize() {\n        let addRow = addButtonProvider(self)\n        addRow.onCellSelection { cell, row in\n            guard !row.isDisabled else { return }\n            guard let tableView = cell.formViewController()?.tableView, let indexPath = row.indexPath else { return }\n            cell.formViewController()?.tableView(tableView, commit: .insert, forRowAt: indexPath)\n        }\n        self <<< addRow\n    }\n\n}\n\n/**\n *  Multivalued sections allows us to easily create insertable, deletable and reorderable sections. By using a multivalued section we can add multiple values for a certain field, such as telephone numbers in a contact.\n */\nopen class MultivaluedSection: GenericMultivaluedSection<ButtonRow> {\n\n    override func initialize() {\n        if addButtonProvider == nil {\n            addButtonProvider = { _ in\n                return ButtonRow {\n                    $0.title = \"Add\"\n                    $0.cellStyle = .value1\n                    }.cellUpdate { cell, _ in\n                        cell.textLabel?.textAlignment = .left\n                }\n            }\n        }\n        super.initialize()\n    }\n\n}\n"
  },
  {
    "path": "Source/Core/SelectableRowType.swift",
    "content": "//  SelectableRowType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\n/**\n *  Every row that shall be used in a SelectableSection must conform to this protocol.\n */\npublic protocol SelectableRowType: RowType {\n    var selectableValue: Cell.Value? { get set }\n}\n"
  },
  {
    "path": "Source/Core/SelectableSection.swift",
    "content": "//  SelectableSection.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: SelectableSection\n\n/**\n Defines how the selection works in a SelectableSection\n \n - MultipleSelection: Multiple options can be selected at once\n - SingleSelection:   Only one selection at a time. Can additionally specify if deselection is enabled or not.\n */\npublic enum SelectionType {\n\n    /**\n     * Multiple options can be selected at once\n     */\n    case multipleSelection\n\n    /**\n     * Only one selection at a time. Can additionally specify if deselection is enabled or not.\n     */\n    case singleSelection(enableDeselection: Bool)\n}\n\n/**\n *  Protocol to be implemented by selectable sections types. Enables easier customization\n */\npublic protocol SelectableSectionType: Collection {\n    associatedtype SelectableRow: BaseRow, SelectableRowType\n\n    /// Defines how the selection works (single / multiple selection)\n    var selectionType: SelectionType { get set }\n\n    /// A closure called when a row of this section is selected.\n    var onSelectSelectableRow: ((SelectableRow.Cell, SelectableRow) -> Void)? { get set }\n\n    func selectedRow() -> SelectableRow?\n    func selectedRows() -> [SelectableRow]\n}\n\nextension SelectableSectionType where Element == BaseRow, Self: AnyObject {\n    /**\n     Returns the selected row of this section. Should be used if selectionType is SingleSelection\n     */\n    public func selectedRow() -> SelectableRow? {\n        return selectedRows().first\n    }\n\n    /**\n     Returns the selected rows of this section. Should be used if selectionType is MultipleSelection\n     */\n    public func selectedRows() -> [SelectableRow] {\n        let selectedRows: [BaseRow] = self.filter { $0 is SelectableRow && $0.baseValue != nil }\n        return selectedRows.map { $0 as! SelectableRow }\n    }\n\n    /**\n     Internal function used to set up a collection of rows before they are added to the section\n     */\n    func prepare(selectableRows rows: [BaseRow]) {\n        for row in rows {\n            if let row = row as? SelectableRow {\n                row.onCellSelection { [weak self] cell, row in\n                    guard let s = self, !row.isDisabled else { return }\n                    switch s.selectionType {\n                    case .multipleSelection:\n                        row.value = row.value == nil ? row.selectableValue : nil\n                    case let .singleSelection(enableDeselection):\n                        s.forEach {\n                            guard $0.baseValue != nil && $0 != row && $0 is SelectableRow else { return }\n                            $0.baseValue = nil\n                            $0.updateCell()\n                        }\n                        // Check if row is not already selected\n                        if row.value == nil {\n                            row.value = row.selectableValue\n                        } else if enableDeselection {\n                            row.value = nil\n                        }\n                    }\n                    row.updateCell()\n                    s.onSelectSelectableRow?(cell, row)\n                }\n            }\n        }\n    }\n\n}\n\n/// A subclass of Section that serves to create a section with a list of selectable options.\nopen class SelectableSection<Row>: Section, SelectableSectionType where Row: SelectableRowType, Row: BaseRow {\n\n    public typealias SelectableRow = Row\n\n    /// Defines how the selection works (single / multiple selection)\n    public var selectionType = SelectionType.singleSelection(enableDeselection: true)\n\n    /// A closure called when a row of this section is selected.\n    public var onSelectSelectableRow: ((Row.Cell, Row) -> Void)?\n\n    public override init(_ initializer: @escaping (SelectableSection<Row>) -> Void) {\n        super.init({ _ in })\n        initializer(self)\n    }\n\n    public init(_ header: String?, selectionType: SelectionType, _ initializer: @escaping (SelectableSection<Row>) -> Void = { _ in }) {\n        self.selectionType = selectionType\n        super.init(header, { _ in })\n        initializer(self)\n    }\n\n    public init(header: String?, footer: String?, selectionType: SelectionType, _ initializer: @escaping (SelectableSection<Row>) -> Void = { _ in }) {\n        self.selectionType = selectionType\n        super.init(header: header, footer: footer, { _ in })\n        initializer(self)\n    }\n\n    public required init() {\n        super.init()\n    }\n\n    #if swift(>=4.1)\n    public required init<S>(_ elements: S) where S : Sequence, S.Element == BaseRow {\n        super.init(elements)\n    }\n    #endif\n\n    open override func rowsHaveBeenAdded(_ rows: [BaseRow], at: IndexSet) {\n        prepare(selectableRows: rows)\n    }\n}\n"
  },
  {
    "path": "Source/Core/SwipeActions.swift",
    "content": "//\n//  Swipe.swift\n//  Eureka\n//\n//  Created by Marco Betschart on 14.06.17.\n//  Copyright © 2017 Xmartlabs. All rights reserved.\n//\n\nimport Foundation\nimport UIKit\n\npublic typealias SwipeActionHandler = (SwipeAction, BaseRow, ((Bool) -> Void)?) -> Void\n\npublic class SwipeAction: ContextualAction {\n    let handler: SwipeActionHandler\n    let style: Style\n\n    public var actionBackgroundColor: UIColor?\n    public var image: UIImage?\n    public var title: String?\n\n    @available (*, deprecated, message: \"Use actionBackgroundColor instead\")\n    public var backgroundColor: UIColor? {\n        get { return actionBackgroundColor }\n        set { self.actionBackgroundColor = newValue }\n    }\n\n    public init(style: Style, title: String?, handler: @escaping SwipeActionHandler){\n        self.style = style\n        self.title = title\n        self.handler = handler\n    }\n\n    func contextualAction(forRow: BaseRow) -> ContextualAction {\n        var action: ContextualAction\n        if #available(iOS 11, *){\n            action = UIContextualAction(style: style.contextualStyle as! UIContextualAction.Style, title: title){ [weak self] action, view, completion -> Void in\n                guard let strongSelf = self else{ return }\n                strongSelf.handler(strongSelf, forRow) { shouldComplete in\n                    if #available(iOS 13, *) { // starting in iOS 13, completion handler is not removing the row automatically, so we need to remove it ourselves\n                        if shouldComplete && action.style == .destructive {\n                            forRow.section?.remove(at: forRow.indexPath!.row)\n                        }\n                    }\n                    completion(shouldComplete)\n                }\n            }\n        } else {\n            action = UITableViewRowAction(style: style.contextualStyle as! UITableViewRowAction.Style,title: title){ [weak self] (action, indexPath) -> Void in\n                guard let strongSelf = self else{ return }\n\t\t\t\tstrongSelf.handler(strongSelf, forRow) { _ in\n\t\t\t\t\tDispatchQueue.main.async {\n\t\t\t\t\t\tguard action.style == .destructive else {\n\t\t\t\t\t\t\tforRow.baseCell?.formViewController()?.tableView?.setEditing(false, animated: true)\n\t\t\t\t\t\t\treturn\n\t\t\t\t\t\t}\n\t\t\t\t\t\tforRow.section?.remove(at: indexPath.row)\n\t\t\t\t\t}\n\t\t\t\t}\n            }\n        }\n        if let color = self.actionBackgroundColor {\n            action.actionBackgroundColor = color\n        }\n        if let image = self.image {\n            action.image = image\n        }\n        return action\n    }\n\t\n    public enum Style {\n        case normal\n        case destructive\n        \n        var contextualStyle: ContextualStyle {\n            if #available(iOS 11, *){\n                switch self{\n                case .normal:\n                    return UIContextualAction.Style.normal\n                case .destructive:\n                    return UIContextualAction.Style.destructive\n                }\n            } else {\n                switch self{\n                case .normal:\n                    return UITableViewRowAction.Style.normal\n                case .destructive:\n                    return UITableViewRowAction.Style.destructive\n                }\n            }\n        }\n    }\n}\n\npublic struct SwipeConfiguration {\n\t\n    unowned var row: BaseRow\n    \n\tinit(_ row: BaseRow){\n\t\tself.row = row\n\t}\n\t\n\tpublic var performsFirstActionWithFullSwipe = false\n\tpublic var actions: [SwipeAction] = []\n}\n\nextension SwipeConfiguration {\n    @available(iOS 11.0, *)\n    var contextualConfiguration: UISwipeActionsConfiguration? {\n        let contextualConfiguration = UISwipeActionsConfiguration(actions: self.contextualActions as! [UIContextualAction])\n        contextualConfiguration.performsFirstActionWithFullSwipe = self.performsFirstActionWithFullSwipe\n        return contextualConfiguration\n    }\n\n    var contextualActions: [ContextualAction]{\n        return self.actions.map { $0.contextualAction(forRow: self.row) }\n    }\n}\n\nprotocol ContextualAction {\n    var actionBackgroundColor: UIColor? { get set }\n    var image: UIImage? { get set }\n    var title: String? { get set }\n}\n\nextension UITableViewRowAction: ContextualAction {\n    public var image: UIImage? {\n        get { return nil }\n        set { return }\n    }\n\n    public var actionBackgroundColor: UIColor? {\n        get { return backgroundColor }\n        set { self.backgroundColor = newValue }\n    }\n}\n\n@available(iOS 11.0, *)\nextension UIContextualAction: ContextualAction {\n\n    public var actionBackgroundColor: UIColor? {\n        get { return backgroundColor }\n        set { self.backgroundColor = newValue }\n    }\n\n}\n\npublic protocol ContextualStyle{}\nextension UITableViewRowAction.Style: ContextualStyle {}\n\n@available(iOS 11.0, *)\nextension UIContextualAction.Style: ContextualStyle {}\n"
  },
  {
    "path": "Source/Core/Validation.swift",
    "content": "//  RowValidationType.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct ValidationError: Equatable {\n\n    public let msg: String\n\n    public init(msg: String) {\n        self.msg = msg\n    }\n}\n\npublic func == (lhs: ValidationError, rhs: ValidationError) -> Bool {\n    return lhs.msg == rhs.msg\n}\n\npublic protocol BaseRuleType {\n    var id: String? { get set }\n    var validationError: ValidationError { get set }\n}\n\npublic protocol RuleType: BaseRuleType {\n    associatedtype RowValueType\n\n    func isValid(value: RowValueType?) -> ValidationError?\n}\n\npublic struct ValidationOptions: OptionSet {\n\n    public let rawValue: Int\n\n    public init(rawValue: Int) {\n        self.rawValue = rawValue\n    }\n\n    public static let validatesOnDemand  = ValidationOptions(rawValue: 1 << 0)\n    public static let validatesOnChange  = ValidationOptions(rawValue: 1 << 1)\n    public static let validatesOnBlur = ValidationOptions(rawValue: 1 << 2)\n    public static let validatesOnChangeAfterBlurred = ValidationOptions(rawValue: 1 << 3)\n\n    public static let validatesAlways: ValidationOptions = [.validatesOnChange, .validatesOnBlur]\n}\n\npublic struct ValidationRuleHelper<T> where T: Equatable {\n    let validateFn: ((T?) -> ValidationError?)\n    public let rule: BaseRuleType\n}\n\npublic struct RuleSet<T: Equatable> {\n\n    internal var rules: [ValidationRuleHelper<T>] = []\n\n    public init() {}\n\n    /// Add a validation Rule to a Row\n    /// - Parameter rule: RuleType object typed to the same type of the Row.value\n    public mutating func add<Rule: RuleType>(rule: Rule) where T == Rule.RowValueType {\n        let validFn: ((T?) -> ValidationError?) = { (val: T?) in\n            return rule.isValid(value: val)\n        }\n        rules.append(ValidationRuleHelper(validateFn: validFn, rule: rule))\n    }\n\n    public mutating func remove(ruleWithIdentifier identifier: String) {\n        if let index = rules.firstIndex(where: { (validationRuleHelper) -> Bool in\n            return validationRuleHelper.rule.id == identifier\n        }) {\n            rules.remove(at: index)\n        }\n    }\n\n    public mutating func removeAllRules() {\n        rules.removeAll()\n    }\n\n}\n"
  },
  {
    "path": "Source/Eureka.h",
    "content": "//  Eureka.h\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\n#import <UIKit/UIKit.h>\n\n//! Project version number for Eureka.\nFOUNDATION_EXPORT double EurekaVersionNumber;\n\n//! Project version string for Eureka.\nFOUNDATION_EXPORT const unsigned char EurekaVersionString[];\n\n// In this header, you should import all the public headers of your framework using statements like #import <Eureka/PublicHeader.h>\n\n\n"
  },
  {
    "path": "Source/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>FMWK</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(MARKETING_VERSION)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(CURRENT_PROJECT_VERSION)</string>\n\t<key>NSPrincipalClass</key>\n\t<string></string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Source/PrivacyInfo.xcprivacy",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>NSPrivacyCollectedDataTypes</key>\n\t<array>\n\t\t<dict>\n\t\t\t<key>NSPrivacyCollectedDataType</key>\n\t\t\t<string>NSPrivacyCollectedDataTypeOtherUsageData</string>\n\t\t\t<key>NSPrivacyCollectedDataTypeLinked</key>\n\t\t\t<false/>\n\t\t\t<key>NSPrivacyCollectedDataTypeTracking</key>\n\t\t\t<false/>\n\t\t\t<key>NSPrivacyCollectedDataTypePurposes</key>\n\t\t\t<array>\n\t\t\t\t<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>\n\t\t\t</array>\n\t\t</dict>\n\t</array>\n</dict>\n</plist>\n"
  },
  {
    "path": "Source/Rows/ActionSheetRow.swift",
    "content": "//  ActionSheetRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class AlertSelectorCell<T> : Cell<T>, CellType where T: Equatable {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        accessoryType = .none\n        editingAccessoryType = accessoryType\n        selectionStyle = row.isDisabled ? .none : .default\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n}\n\nopen class _ActionSheetRow<Cell: CellType>: AlertOptionsRow<Cell>, PresenterRowType where Cell: BaseCell {\n\n    public typealias ProviderType = SelectorAlertController<_ActionSheetRow<Cell>>\n    \n    public var onPresentCallback: ((FormViewController, ProviderType) -> Void)?\n    lazy public var presentationMode: PresentationMode<ProviderType>? = {\n        return .presentModally(controllerProvider: ControllerProvider.callback { [weak self] in\n            let vc = SelectorAlertController<_ActionSheetRow<Cell>>(title: self?.selectorTitle, message: nil, preferredStyle: .actionSheet)\n            if let popView = vc.popoverPresentationController {\n                guard let cell = self?.cell, let tableView = cell.formViewController()?.tableView else { fatalError() }\n                popView.sourceView = tableView\n                popView.sourceRect = tableView.convert(cell.detailTextLabel?.frame ?? cell.textLabel?.frame ?? cell.contentView.frame, from: cell)\n            }\n            vc.row = self\n            return vc\n        },\n        onDismiss: { [weak self] in\n            $0.dismiss(animated: true)\n            self?.cell?.formViewController()?.tableView?.reloadData()\n        })\n    }()\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    open override func customDidSelect() {\n        super.customDidSelect()\n        if let presentationMode = presentationMode, !isDisabled {\n            if let controller = presentationMode.makeController() {\n                controller.row = self\n                onPresentCallback?(cell.formViewController()!, controller)\n                presentationMode.present(controller, row: self, presentingController: cell.formViewController()!)\n            } else {\n                presentationMode.present(nil, row: self, presentingController: cell.formViewController()!)\n            }\n        }\n    }\n}\n\n/// An options row where the user can select an option from an ActionSheet\npublic final class ActionSheetRow<T>: _ActionSheetRow<AlertSelectorCell<T>>, RowType where T: Equatable {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/AlertRow.swift",
    "content": "//  AlertRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\nimport Foundation\nimport UIKit\n\nopen class _AlertRow<Cell: CellType>: AlertOptionsRow<Cell>, PresenterRowType where Cell: BaseCell {\n\n    public typealias PresentedController = SelectorAlertController<_AlertRow<Cell>>\n    \n    open var onPresentCallback: ((FormViewController, PresentedController) -> Void)?\n    lazy open var presentationMode: PresentationMode<PresentedController>? = {\n        return .presentModally(controllerProvider: ControllerProvider<PresentedController>.callback { [weak self] in\n            let vc = PresentedController(title: self?.selectorTitle, message: nil, preferredStyle: .alert)\n            vc.row = self\n            return vc\n        }, onDismiss: { [weak self] in\n            $0.dismiss(animated: true)\n            self?.cell?.formViewController()?.tableView?.reloadData()\n        })\n    }()\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    open override func customDidSelect() {\n        super.customDidSelect()\n        if let presentationMode = presentationMode, !isDisabled {\n            if let controller = presentationMode.makeController() {\n                controller.row = self\n                onPresentCallback?(cell.formViewController()!, controller)\n                presentationMode.present(controller, row: self, presentingController: cell.formViewController()!)\n            } else {\n                presentationMode.present(nil, row: self, presentingController: cell.formViewController()!)\n            }\n        }\n    }\n}\n\n/// An options row where the user can select an option from a modal Alert\npublic final class AlertRow<T: Equatable>: _AlertRow<AlertSelectorCell<T>>, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/ButtonRow.swift",
    "content": "//  ButtonRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: ButtonCell\n\nopen class ButtonCellOf<T: Equatable>: Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n        accessoryType = .none\n        editingAccessoryType = accessoryType\n        textLabel?.textAlignment = .center\n        textLabel?.textColor = tintColor.withAlphaComponent(row.isDisabled ? 0.3 : 1.0)\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n}\n\npublic typealias ButtonCell = ButtonCellOf<String>\n\n// MARK: ButtonRow\n\nopen class _ButtonRowOf<T: Equatable> : Row<ButtonCellOf<T>> {\n    open var presentationMode: PresentationMode<UIViewController>?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n        cellStyle = .default\n    }\n\n    open override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            if let presentationMode = presentationMode {\n                if let controller = presentationMode.makeController() {\n                    presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n                } else {\n                    presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n                }\n            }\n        }\n    }\n\n    open override func customUpdateCell() {\n        super.customUpdateCell()\n        let leftAligmnment = presentationMode != nil\n        cell.textLabel?.textAlignment = leftAligmnment ? .left : .center\n        cell.accessoryType = !leftAligmnment || isDisabled ? .none : .disclosureIndicator\n        cell.editingAccessoryType = cell.accessoryType\n        cell.textLabel?.textColor = !leftAligmnment ? cell.tintColor.withAlphaComponent(isDisabled ? 0.3 : 1.0) : nil\n    }\n\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        (segue.destination as? RowControllerType)?.onDismissCallback = presentationMode?.onDismissCallback\n    }\n}\n\n/// A generic row with a button. The action of this button can be anything but normally will push a new view controller\npublic final class ButtonRowOf<T: Equatable> : _ButtonRowOf<T>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with a button and String value. The action of this button can be anything but normally will push a new view controller\npublic typealias ButtonRow = ButtonRowOf<String>\n"
  },
  {
    "path": "Source/Rows/ButtonRowWithPresent.swift",
    "content": "//  Rows.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class _ButtonRowWithPresent<VCType: TypedRowControllerType>: Row<ButtonCellOf<VCType.RowValue>>, PresenterRowType where VCType: UIViewController {\n\n    open var presentationMode: PresentationMode<VCType>?\n    open var onPresentCallback: ((FormViewController, VCType) -> Void)?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n        cellStyle = .default\n    }\n\n    open override func customUpdateCell() {\n        super.customUpdateCell()\n        let leftAligmnment = presentationMode != nil\n        cell.textLabel?.textAlignment = leftAligmnment ? .left : .center\n        cell.accessoryType = !leftAligmnment || isDisabled ? .none : .disclosureIndicator\n        cell.editingAccessoryType = cell.accessoryType\n        if !leftAligmnment {\n            var red: CGFloat = 0, green: CGFloat = 0, blue: CGFloat = 0, alpha: CGFloat = 0\n            cell.tintColor.getRed(&red, green: &green, blue: &blue, alpha: &alpha)\n            cell.textLabel?.textColor  = UIColor(red: red, green: green, blue: blue, alpha:isDisabled ? 0.3 : 1.0)\n        } else {\n            cell.textLabel?.textColor = nil\n        }\n    }\n\n    open override func customDidSelect() {\n        super.customDidSelect()\n        if let presentationMode = presentationMode, !isDisabled {\n            if let controller = presentationMode.makeController() {\n                controller.row = self\n                onPresentCallback?(cell.formViewController()!, controller)\n                presentationMode.present(controller, row: self, presentingController: cell.formViewController()!)\n            } else {\n                presentationMode.present(nil, row: self, presentingController: cell.formViewController()!)\n            }\n        }\n    }\n\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as? VCType else {\n            return\n        }\n        if let callback = presentationMode?.onDismissCallback {\n            rowVC.onDismissCallback = callback\n        }\n        rowVC.row = self\n        onPresentCallback?(cell.formViewController()!, rowVC)\n    }\n\n}\n\n// MARK: Rows\n\n/// A generic row with a button that presents a view controller when tapped\npublic final class ButtonRowWithPresent<VCType: TypedRowControllerType> : _ButtonRowWithPresent<VCType>, RowType where VCType: UIViewController {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/CheckRow.swift",
    "content": "//  CheckRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: CheckCell\n\nopen class CheckCell: Cell<Bool>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        accessoryType = row.value == true ? .checkmark : .none\n        editingAccessoryType = accessoryType\n        selectionStyle = .default\n        if row.isDisabled {\n            tintAdjustmentMode = .dimmed\n            selectionStyle = .none\n        } else {\n            tintAdjustmentMode = .automatic\n        }\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .checkmark\n        editingAccessoryType = accessoryType\n    }\n\n    open override func didSelect() {\n        row.value = row.value ?? false ? false : true\n        row.deselect()\n        row.updateCell()\n    }\n\n}\n\n// MARK: CheckRow\n\nopen class _CheckRow: Row<CheckCell> {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n    }\n}\n\n///// Boolean row that has a checkmark as accessoryType\npublic final class CheckRow: _CheckRow, RowType {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/AlertOptionsRow.swift",
    "content": "//\n//  AlertOptionsRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\n\nimport Foundation\n\nopen class AlertOptionsRow<Cell: CellType> : OptionsRow<Cell>, AlertOptionsProviderRow where Cell: BaseCell {\n\n    typealias OptionsProviderType = OptionsProvider<Cell.Value>\n\n    open var cancelTitle: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n}\n"
  },
  {
    "path": "Source/Rows/Common/DateFieldRow.swift",
    "content": "//  DateFieldRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\npublic protocol DatePickerRowProtocol: AnyObject {\n    var minimumDate: Date? { get set }\n    var maximumDate: Date? { get set }\n    var minuteInterval: Int? { get set }\n}\n\nopen class DateCell: Cell<Date>, CellType {\n\n    public var datePicker: UIDatePicker\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        datePicker = UIDatePicker()\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        datePicker = UIDatePicker()\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .none\n        editingAccessoryType =  .none\n        datePicker.datePickerMode = datePickerMode()\n        datePicker.addTarget(self, action: #selector(DateCell.datePickerValueDidChange(_:)), for: .valueChanged)\n\n        #if swift(>=5.2)\n            if #available(iOS 13.4, *) {\n                datePicker.preferredDatePickerStyle = .wheels\n            }\n        #endif\n    }\n\n    deinit {\n        datePicker.removeTarget(self, action: nil, for: .allEvents)\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n        datePicker.setDate(row.value ?? Date(), animated: row is CountDownPickerRow)\n        datePicker.minimumDate = (row as? DatePickerRowProtocol)?.minimumDate\n        datePicker.maximumDate = (row as? DatePickerRowProtocol)?.maximumDate\n        if let minuteIntervalValue = (row as? DatePickerRowProtocol)?.minuteInterval {\n            datePicker.minuteInterval = minuteIntervalValue\n        }\n        if row.isHighlighted {\n            textLabel?.textColor = tintColor\n        }\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n\n    override open var inputView: UIView? {\n        if let v = row.value {\n            datePicker.setDate(v, animated:row is CountDownRow)\n        }\n        return datePicker\n    }\n\n    @objc(datePickerValueDidChange:) func datePickerValueDidChange(_ sender: UIDatePicker) {\n        row.value = sender.date\n        detailTextLabel?.text = row.displayValueFor?(row.value)\n    }\n\n    private func datePickerMode() -> UIDatePicker.Mode {\n        switch row {\n        case is DateRow:\n            return .date\n        case is TimeRow:\n            return .time\n        case is DateTimeRow:\n            return .dateAndTime\n        case is CountDownRow:\n            return .countDownTimer\n        default:\n            return .date\n        }\n    }\n\n    open override func cellCanBecomeFirstResponder() -> Bool {\n        return canBecomeFirstResponder\n    }\n\n    override open var canBecomeFirstResponder: Bool {\n        return !row.isDisabled\n    }\n}\n\nopen class _DateFieldRow: Row<DateCell>, DatePickerRowProtocol, NoValueDisplayTextConformance {\n\n    /// The minimum value for this row's UIDatePicker\n    open var minimumDate: Date?\n\n    /// The maximum value for this row's UIDatePicker\n    open var maximumDate: Date?\n\n    /// The interval between options for this row's UIDatePicker\n    open var minuteInterval: Int?\n\n    /// The formatter for the date picked by the user\n    open var dateFormatter: DateFormatter?\n\n    open var noValueDisplayText: String? = nil\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = { [unowned self] value in\n            guard let val = value, let formatter = self.dateFormatter else { return nil }\n            return formatter.string(from: val)\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/DateInlineFieldRow.swift",
    "content": "//  DateInlineFieldRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class DateInlineCell: Cell<Date>, CellType {\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .none\n        editingAccessoryType =  .none\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n}\n\nopen class _DateInlineFieldRow: Row<DateInlineCell>, DatePickerRowProtocol, NoValueDisplayTextConformance {\n\n    /// The minimum value for this row's UIDatePicker\n    open var minimumDate: Date?\n\n    /// The maximum value for this row's UIDatePicker\n    open var maximumDate: Date?\n\n    /// The interval between options for this row's UIDatePicker\n    open var minuteInterval: Int?\n\n    /// The formatter for the date picked by the user\n    open var dateFormatter: DateFormatter?\n\n    open var noValueDisplayText: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter = DateFormatter()\n        dateFormatter?.locale = Locale.current\n        displayValueFor = { [unowned self] value in\n            guard let val = value, let formatter = self.dateFormatter else { return nil }\n            return formatter.string(from: val)\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/DecimalFormatter.swift",
    "content": "//  DecimalFormatter.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// A custom formatter for numbers with two digits after the decimal mark\nopen class DecimalFormatter: NumberFormatter, FormatterProtocol {\n\n    /// Creates the formatter with 2 Fraction Digits, Locale set to .current and .decimal NumberFormatter.Style\n    public override init() {\n        super.init()\n        locale = Locale.current\n        numberStyle = .decimal\n        minimumFractionDigits = 2\n        maximumFractionDigits = 2\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        fatalError(\"init(coder:) has not been implemented\")\n    }\n\n    /// Creates an NSNumber from the given String\n    /// - Parameter obj: Pointer to NSNumber object to assign\n    /// - Parameter string: String with number assumed to have the configured min. fraction digits.\n    /// - Parameter rangep: Unused range parameter\n    override open func getObjectValue(_ obj: AutoreleasingUnsafeMutablePointer<AnyObject?>?, for string: String, range rangep: UnsafeMutablePointer<NSRange>?) throws {\n        guard obj != nil else { return  }\n        let str = string.components(separatedBy: CharacterSet.decimalDigits.inverted).joined(separator: \"\")\n        // Recover the number from the string in a way that forces the formatter's fraction digits\n        // numberWithoutDecimals / 10 ^ minimumFractionDigits\n        obj?.pointee = NSNumber(value: (Double(str) ?? 0.0)/Double(pow(10.0, Double(minimumFractionDigits))))\n    }\n\n    open func getNewPosition(forPosition position: UITextPosition, inTextInput textInput: UITextInput, oldValue: String?, newValue: String?) -> UITextPosition {\n        return textInput.position(from: position, offset:((newValue?.count ?? 0) - (oldValue?.count ?? 0))) ?? position\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/FieldRow.swift",
    "content": "//  FieldRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\npublic protocol InputTypeInitiable {\n    init?(string stringValue: String)\n}\n\npublic protocol FieldRowConformance : FormatterConformance {\n    var titlePercentage : CGFloat? { get set }\n    var placeholder : String? { get set }\n    var placeholderColor : UIColor? { get set }\n}\n\nextension Int: InputTypeInitiable {\n\n    public init?(string stringValue: String) {\n        self.init(stringValue, radix: 10)\n    }\n}\nextension Float: InputTypeInitiable {\n    public init?(string stringValue: String) {\n        self.init(stringValue)\n    }\n}\nextension String: InputTypeInitiable {\n    public init?(string stringValue: String) {\n        self.init(stringValue)\n    }\n}\nextension URL: InputTypeInitiable {}\nextension Double: InputTypeInitiable {\n    public init?(string stringValue: String) {\n        self.init(stringValue)\n    }\n}\n\nopen class FormatteableRow<Cell: CellType>: Row<Cell>, FormatterConformance where Cell: BaseCell, Cell: TextInputCell {\n\n    /// A formatter to be used to format the user's input\n    open var formatter: Formatter?\n\n    /// If the formatter should be used while the user is editing the text.\n    open var useFormatterDuringInput = false\n    open var useFormatterOnDidBeginEditing: Bool?\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = { [unowned self] value in\n            guard let v = value else { return nil }\n            guard let formatter = self.formatter else { return String(describing: v) }\n            if (self.cell.textInput as? UIView)?.isFirstResponder == true {\n                return self.useFormatterDuringInput ? formatter.editingString(for: v) : String(describing: v)\n            }\n            return formatter.string(for: v)\n        }\n    }\n\n}\n\nopen class FieldRow<Cell: CellType>: FormatteableRow<Cell>, FieldRowConformance, KeyboardReturnHandler where Cell: BaseCell, Cell: TextFieldCell {\n\n    /// Configuration for the keyboardReturnType of this row\n    open var keyboardReturnType: KeyboardReturnTypeConfiguration?\n\n    /// The percentage of the cell that should be occupied by the textField\n\t@available (*, deprecated, message: \"Use titlePercentage instead\")\n\topen var textFieldPercentage : CGFloat? {\n\t\tget {\n\t\t\treturn titlePercentage.map { 1 - $0 }\n\t\t}\n\t\tset {\n\t\t\ttitlePercentage = newValue.map { 1 - $0 }\n\t\t}\n\t}\n\n\t/// The percentage of the cell that should be occupied by the title (i.e. the titleLabel and optional imageView combined)\n\topen var titlePercentage: CGFloat?\n\n    /// The placeholder for the textField\n    open var placeholder: String?\n\n    /// The textColor for the textField's placeholder\n    open var placeholderColor: UIColor?\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/**\n *  Protocol for cells that contain a UITextField\n */\npublic protocol TextInputCell {\n    var textInput: UITextInput { get }\n}\n\npublic protocol TextFieldCell: TextInputCell {\n    var textField: UITextField! { get }\n}\n\nextension TextFieldCell {\n\n    public var textInput: UITextInput {\n        return textField\n    }\n}\n\nopen class _FieldCell<T> : Cell<T>, UITextFieldDelegate, TextFieldCell where T: Equatable, T: InputTypeInitiable {\n\n    @IBOutlet public weak var textField: UITextField!\n    @IBOutlet public weak var titleLabel: UILabel?\n\n    fileprivate var observingTitleText = false\n    private var awakeFromNibCalled = false\n\n    open var dynamicConstraints = [NSLayoutConstraint]()\n\n\tprivate var calculatedTitlePercentage: CGFloat = 0.7\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n\n        let textField = UITextField()\n        self.textField = textField\n        textField.translatesAutoresizingMaskIntoConstraints = false\n\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n        setupTitleLabel()\n\n        contentView.addSubview(titleLabel!)\n        contentView.addSubview(textField)\n\n        NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            guard me.observingTitleText else { return }\n            me.titleLabel?.removeObserver(me, forKeyPath: \"text\")\n            me.observingTitleText = false\n        }\n        NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            guard !me.observingTitleText else { return }\n            me.titleLabel?.addObserver(me, forKeyPath: \"text\", options: [.new, .old], context: nil)\n            me.observingTitleText = true\n        }\n\n        NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: nil) { [weak self] _ in\n            self?.setupTitleLabel()\n            self?.setNeedsUpdateConstraints()\n        }\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func awakeFromNib() {\n        super.awakeFromNib()\n        awakeFromNibCalled = true\n    }\n\n    deinit {\n        textField?.delegate = nil\n        textField?.removeTarget(self, action: nil, for: .allEvents)\n        guard !awakeFromNibCalled else { return }\n        if observingTitleText {\n            titleLabel?.removeObserver(self, forKeyPath: \"text\")\n        }\n        imageView?.removeObserver(self, forKeyPath: \"image\")\n        NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)\n        NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)\n        NotificationCenter.default.removeObserver(self, name: UIContentSizeCategory.didChangeNotification, object: nil)\n    }\n\n    open override func setup() {\n        super.setup()\n        selectionStyle = .none\n\n        if !awakeFromNibCalled {\n            titleLabel?.addObserver(self, forKeyPath: \"text\", options: [.new, .old], context: nil)\n            observingTitleText = true\n            imageView?.addObserver(self, forKeyPath: \"image\", options: [.new, .old], context: nil)\n        }\n        textField.addTarget(self, action: #selector(_FieldCell.textFieldDidChange(_:)), for: .editingChanged)\n\n        if let titleLabel = titleLabel {\n            // Make sure the title takes over most of the empty space so that the text field starts editing at the back.\n            let priority = UILayoutPriority(rawValue: titleLabel.contentHuggingPriority(for: .horizontal).rawValue + 1)\n            textField.setContentHuggingPriority(priority, for: .horizontal)\n        }\n    }\n\n    open override func update() {\n        super.update()\n        detailTextLabel?.text = nil\n\n        if !awakeFromNibCalled {\n            if let title = row.title {\n                switch row.cellStyle {\n                case .subtitle:\n                    textField.textAlignment = .left\n                    textField.clearButtonMode = .whileEditing\n                default:\n                    textField.textAlignment = title.isEmpty ? .left : .right\n                    textField.clearButtonMode = title.isEmpty ? .whileEditing : .never\n                }\n            } else {\n                textField.textAlignment = .left\n                textField.clearButtonMode = .whileEditing\n            }\n        } else {\n            textLabel?.text = nil\n            titleLabel?.text = row.title\n            if #available(iOS 13.0, *) {\n                titleLabel?.textColor = row.isDisabled ? .tertiaryLabel : .label\n            } else {\n                titleLabel?.textColor = row.isDisabled ? .gray : .black\n            }\n        }\n        textField.delegate = self\n        textField.text = row.displayValueFor?(row.value)\n        textField.isEnabled = !row.isDisabled\n        if #available(iOS 13.0, *) {\n            textField.textColor = row.isDisabled ? .tertiaryLabel : .label\n        } else {\n            textField.textColor = row.isDisabled ? .gray : .black\n        }\n        textField.font = .preferredFont(forTextStyle: .body)\n        if let placeholder = (row as? FieldRowConformance)?.placeholder {\n            if let color = (row as? FieldRowConformance)?.placeholderColor {\n                textField.attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [.foregroundColor: color])\n            } else {\n                textField.placeholder = (row as? FieldRowConformance)?.placeholder\n            }\n        }\n        if row.isHighlighted {\n            titleLabel?.textColor = tintColor\n        }\n    }\n\n    open override func cellCanBecomeFirstResponder() -> Bool {\n        return !row.isDisabled && textField?.canBecomeFirstResponder == true\n    }\n\n    open override func cellBecomeFirstResponder(withDirection: Direction) -> Bool {\n        return textField.becomeFirstResponder()\n    }\n\n    open override func cellResignFirstResponder() -> Bool {\n        return textField.resignFirstResponder()\n    }\n\n    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n        let obj = object as AnyObject?\n\n        if let keyPathValue = keyPath, let changeType = change?[NSKeyValueChangeKey.kindKey],\n            ((obj === titleLabel && keyPathValue == \"text\") || (obj === imageView && keyPathValue == \"image\")) &&\n                (changeType as? NSNumber)?.uintValue == NSKeyValueChange.setting.rawValue {\n            setNeedsUpdateConstraints()\n            updateConstraintsIfNeeded()\n        }\n    }\n\n    // MARK: Helpers\n\n    open func customConstraints() {\n\n        guard !awakeFromNibCalled else { return }\n        contentView.removeConstraints(dynamicConstraints)\n        dynamicConstraints = []\n        \n        switch row.cellStyle {\n        case .subtitle:\n            var views: [String: AnyObject] =  [\"textField\": textField]\n            \n            if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                views[\"titleLabel\"] = titleLabel\n                dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[titleLabel]-3-[textField]-|\",\n                                                                     options: .alignAllLeading, metrics: nil, views: views)\n                titleLabel.setContentHuggingPriority(\n                    UILayoutPriority(textField.contentHuggingPriority(for: .vertical).rawValue + 1), for: .vertical)\n                dynamicConstraints.append(NSLayoutConstraint(item: titleLabel, attribute: .centerX, relatedBy: .equal, toItem: textField, attribute: .centerX, multiplier: 1, constant: 0))\n            } else {\n                dynamicConstraints.append(NSLayoutConstraint(item: textField!, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0))\n            }\n            \n            if let imageView = imageView, let _ = imageView.image {\n                views[\"imageView\"] = imageView\n                if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[titleLabel]-|\", options: [], metrics: nil, views: views)\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[textField]-|\", options: [], metrics: nil, views: views)\n                } else {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[textField]-|\", options: [], metrics: nil, views: views)\n                }\n            } else {\n                if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[titleLabel]-|\", options: [], metrics: nil, views: views)\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[textField]-|\", options: [], metrics: nil, views: views)\n                } else {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[textField]-|\", options: .alignAllLeft, metrics: nil, views: views)\n                }\n            }\n            \n        default:\n            var views: [String: AnyObject] =  [\"textField\": textField]\n            dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[textField]-|\", options: .alignAllLastBaseline, metrics: nil, views: views)\n            \n            if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                views[\"titleLabel\"] = titleLabel\n                dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[titleLabel]-|\", options: .alignAllLastBaseline, metrics: nil, views: views)\n                dynamicConstraints.append(NSLayoutConstraint(item: titleLabel, attribute: .centerY, relatedBy: .equal, toItem: textField, attribute: .centerY, multiplier: 1, constant: 0))\n            }\n            \n            if let imageView = imageView, let _ = imageView.image {\n                views[\"imageView\"] = imageView\n                if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[titleLabel]-[textField]-|\", options: [], metrics: nil, views: views)\n                    dynamicConstraints.append(NSLayoutConstraint(item: titleLabel,\n                                                                 attribute: .width,\n                                                                 relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual,\n                                                                 toItem: contentView,\n                                                                 attribute: .width,\n                                                                 multiplier: calculatedTitlePercentage,\n                                                                 constant: 0.0))\n                } else {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[textField]-|\", options: [], metrics: nil, views: views)\n                }\n            } else {\n                if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[titleLabel]-[textField]-|\", options: [], metrics: nil, views: views)\n                    dynamicConstraints.append(NSLayoutConstraint(item: titleLabel,\n                                                                 attribute: .width,\n                                                                 relatedBy: (row as? FieldRowConformance)?.titlePercentage != nil ? .equal : .lessThanOrEqual,\n                                                                 toItem: contentView,\n                                                                 attribute: .width,\n                                                                 multiplier: calculatedTitlePercentage,\n                                                                 constant: 0.0))\n                } else {\n                    dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[textField]-|\", options: .alignAllLeft, metrics: nil, views: views)\n                }\n            }\n        }\n        contentView.addConstraints(dynamicConstraints)\n    }\n\n    open override func updateConstraints() {\n        customConstraints()\n        super.updateConstraints()\n    }\n\n    @objc open func textFieldDidChange(_ textField: UITextField) {\n        \n        guard textField.markedTextRange == nil else { return }\n\n        guard let textValue = textField.text else {\n            row.value = nil\n            return\n        }\n        guard let fieldRow = row as? FieldRowConformance, let formatter = fieldRow.formatter else {\n            row.value = textValue.isEmpty ? nil : (T.init(string: textValue) ?? row.value)\n            return\n        }\n        if fieldRow.useFormatterDuringInput {\n            let unsafePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)\n            defer {\n                unsafePointer.deallocate()\n            }\n            let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(unsafePointer)\n            let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n            if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                row.value = value.pointee as? T\n                guard var selStartPos = textField.selectedTextRange?.start else { return }\n                let oldVal = textField.text\n                textField.text = row.displayValueFor?(row.value)\n                selStartPos = (formatter as? FormatterProtocol)?.getNewPosition(forPosition: selStartPos, inTextInput: textField, oldValue: oldVal, newValue: textField.text) ?? selStartPos\n                textField.selectedTextRange = textField.textRange(from: selStartPos, to: selStartPos)\n                return\n            }\n        } else {\n            let unsafePointer = UnsafeMutablePointer<T>.allocate(capacity: 1)\n            defer {\n                unsafePointer.deallocate()\n            }\n            let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(unsafePointer)\n            let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n            if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                row.value = value.pointee as? T\n            } else {\n                row.value = textValue.isEmpty ? nil : (T.init(string: textValue) ?? row.value)\n            }\n        }\n    }\n\n    // MARK: Helpers\n\n    private func setupTitleLabel() {\n        titleLabel = self.textLabel\n        titleLabel?.translatesAutoresizingMaskIntoConstraints = false\n        titleLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n        titleLabel?.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .horizontal)\n    }\n\n    private func displayValue(useFormatter: Bool) -> String? {\n        guard let v = row.value else { return nil }\n        if let formatter = (row as? FormatterConformance)?.formatter, useFormatter {\n            return textField?.isFirstResponder == true ? formatter.editingString(for: v) : formatter.string(for: v)\n        }\n        return String(describing: v)\n    }\n\n    // MARK: TextFieldDelegate\n\n    open func textFieldDidBeginEditing(_ textField: UITextField) {\n        formViewController()?.beginEditing(of: self)\n        formViewController()?.textInputDidBeginEditing(textField, cell: self)\n        if let fieldRowConformance = row as? FormatterConformance, let _ = fieldRowConformance.formatter, fieldRowConformance.useFormatterOnDidBeginEditing ?? fieldRowConformance.useFormatterDuringInput {\n            textField.text = displayValue(useFormatter: true)\n        } else {\n            textField.text = displayValue(useFormatter: false)\n        }\n    }\n\n    open func textFieldDidEndEditing(_ textField: UITextField) {\n        formViewController()?.endEditing(of: self)\n        formViewController()?.textInputDidEndEditing(textField, cell: self)\n        textFieldDidChange(textField)\n        textField.text = displayValue(useFormatter: (row as? FormatterConformance)?.formatter != nil)\n    }\n\n    open func textFieldShouldReturn(_ textField: UITextField) -> Bool {\n        return formViewController()?.textInputShouldReturn(textField, cell: self) ?? true\n    }\n\n    open func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {\n        return formViewController()?.textInput(textField, shouldChangeCharactersInRange:range, replacementString:string, cell: self) ?? true\n    }\n\n    open func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {\n        return formViewController()?.textInputShouldBeginEditing(textField, cell: self) ?? true\n    }\n\n    open func textFieldShouldClear(_ textField: UITextField) -> Bool {\n        return formViewController()?.textInputShouldClear(textField, cell: self) ?? true\n    }\n\n    open func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {\n        return formViewController()?.textInputShouldEndEditing(textField, cell: self) ?? true\n\t}\n\n\topen override func layoutSubviews() {\n\t\tsuper.layoutSubviews()\n\t\tguard let row = (row as? FieldRowConformance) else { return }\n\t\tdefer {\n\t\t\t// As titleLabel is the textLabel, iOS may re-layout without updating constraints, for example:\n\t\t\t// swiping, showing alert or actionsheet from the same section.\n\t\t\t// thus we need forcing update to use customConstraints()\n\t\t\tsetNeedsUpdateConstraints()\n\t\t\tupdateConstraintsIfNeeded()\n\t\t}\n\t\tguard let titlePercentage = row.titlePercentage else  { return }\n\t\tvar targetTitleWidth = bounds.size.width * titlePercentage\n\t\tif let imageView = imageView, let _ = imageView.image, let titleLabel = titleLabel {\n\t\t\tvar extraWidthToSubtract = titleLabel.frame.minX - imageView.frame.minX // Left-to-right interface layout\n            if UIView.userInterfaceLayoutDirection(for: self.semanticContentAttribute) == .rightToLeft {\n                extraWidthToSubtract = imageView.frame.maxX - titleLabel.frame.maxX\n            }\n\t\t\ttargetTitleWidth -= extraWidthToSubtract\n\t\t}\n\t\tcalculatedTitlePercentage = targetTitleWidth / contentView.bounds.size.width\n\t}\n}\n"
  },
  {
    "path": "Source/Rows/Common/GenericMultipleSelectorRow.swift",
    "content": "//  GenericMultipleSelectorRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// Generic options selector row that allows multiple selection.\nopen class GenericMultipleSelectorRow<T, Cell: CellType>: Row<Cell>, PresenterRowType, NoValueDisplayTextConformance, OptionsProviderRow\n            where Cell: BaseCell, Cell.Value == Set<T> {\n    \n    public typealias PresentedController = MultipleSelectorViewController<GenericMultipleSelectorRow<T,Cell>>\n\n    /// Defines how the view controller will be presented, pushed, etc.\n    open var presentationMode: PresentationMode<PresentedController>?\n\n    /// Will be called before the presentation occurs.\n    open var onPresentCallback: ((FormViewController, PresentedController) -> Void)?\n\n    /// Title to be displayed for the options\n    open var selectorTitle: String?\n    open var noValueDisplayText: String?\n\n    /// Options from which the user will choose\n    open var optionsProvider: OptionsProvider<T>?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = { (rowValue: Set<T>?) in\n            return rowValue?.map({ String(describing: $0) }).sorted().joined(separator: \", \")\n        }\n        presentationMode = .show(controllerProvider: ControllerProvider.callback {\n                return MultipleSelectorViewController<GenericMultipleSelectorRow<T,Cell>>()\n        }, onDismiss: { vc in\n            let _ = vc.navigationController?.popViewController(animated: true)\n        })\n    }\n\n    /**\n     Extends `didSelect` method\n     */\n    open override func customDidSelect() {\n        super.customDidSelect()\n        guard let presentationMode = presentationMode, !isDisabled else { return }\n        if let controller = presentationMode.makeController() {\n            controller.row = self\n            controller.title = selectorTitle ?? controller.title\n            onPresentCallback?(cell.formViewController()!, controller)\n            presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n        } else {\n            presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n        }\n    }\n\n    /**\n     Prepares the pushed row setting its title and completion callback.\n     */\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as Any as? PresentedController else { return }\n        rowVC.title = selectorTitle ?? rowVC.title\n        rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback\n        onPresentCallback?(cell.formViewController()!, rowVC)\n        rowVC.row = self\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/OptionsRow.swift",
    "content": "//  OptionsRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\nopen class OptionsRow<Cell: CellType> : Row<Cell>, NoValueDisplayTextConformance, OptionsProviderRow where Cell: BaseCell {\n    \n    open var optionsProvider: OptionsProvider<Cell.Value>?\n    \n    open var selectorTitle: String?\n    open var noValueDisplayText: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Common/Protocols.swift",
    "content": "//  Protocols.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic protocol FormatterConformance: AnyObject {\n    var formatter: Formatter? { get set }\n    var useFormatterDuringInput: Bool { get set }\n    var useFormatterOnDidBeginEditing: Bool? { get set }\n}\n\npublic protocol NoValueDisplayTextConformance: AnyObject {\n    var noValueDisplayText: String? { get set }\n}\n"
  },
  {
    "path": "Source/Rows/Common/SelectorRow.swift",
    "content": "//  SelectorRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class PushSelectorCell<T: Equatable> : Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        accessoryType = .disclosureIndicator\n        editingAccessoryType = accessoryType\n        selectionStyle = row.isDisabled ? .none : .default\n    }\n}\n\n/// Generic row type where a user must select a value among several options.\nopen class SelectorRow<Cell: CellType>: OptionsRow<Cell>, PresenterRowType where Cell: BaseCell {\n\n    \n    /// Defines how the view controller will be presented, pushed, etc.\n    open var presentationMode: PresentationMode<SelectorViewController<SelectorRow<Cell>>>?\n\n    /// Will be called before the presentation occurs.\n    open var onPresentCallback: ((FormViewController, SelectorViewController<SelectorRow<Cell>>) -> Void)?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    /**\n     Extends `didSelect` method\n     */\n    open override func customDidSelect() {\n        super.customDidSelect()\n        guard let presentationMode = presentationMode, !isDisabled else { return }\n        if let controller = presentationMode.makeController() {\n            controller.row = self\n            controller.title = selectorTitle ?? controller.title\n            onPresentCallback?(cell.formViewController()!, controller)\n            presentationMode.present(controller, row: self, presentingController: self.cell.formViewController()!)\n        } else {\n            presentationMode.present(nil, row: self, presentingController: self.cell.formViewController()!)\n        }\n    }\n\n    /**\n     Prepares the pushed row setting its title and completion callback.\n     */\n    open override func prepare(for segue: UIStoryboardSegue) {\n        super.prepare(for: segue)\n        guard let rowVC = segue.destination as Any as? SelectorViewController<SelectorRow<Cell>> else { return }\n        rowVC.title = selectorTitle ?? rowVC.title\n        rowVC.onDismissCallback = presentationMode?.onDismissCallback ?? rowVC.onDismissCallback\n        onPresentCallback?(cell.formViewController()!, rowVC)\n        rowVC.row = self\n    }\n}\n"
  },
  {
    "path": "Source/Rows/Controllers/MultipleSelectorViewController.swift",
    "content": "//  MultipleSelectorViewController.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// Selector Controller that enables multiple selection\nopen class _MultipleSelectorViewController<Row: SelectableRowType, OptionsRow: OptionsProviderRow> : FormViewController, TypedRowControllerType where Row: BaseRow, Row.Cell.Value == OptionsRow.OptionsProviderType.Option, OptionsRow.OptionsProviderType.Option: Hashable {\n\n    /// The row that pushed or presented this controller\n    public var row: RowOf<Set<OptionsRow.OptionsProviderType.Option>>!\n\n    public var selectableRowSetup: ((_ row: Row) -> Void)?\n    public var selectableRowCellSetup: ((_ cell: Row.Cell, _ row: Row) -> Void)?\n    public var selectableRowCellUpdate: ((_ cell: Row.Cell, _ row: Row) -> Void)?\n    \n    /// A closure to be called when the controller disappears.\n    public var onDismissCallback: ((UIViewController) -> Void)?\n\n    /// A closure that should return key for particular row value.\n    /// This key is later used to break options by sections.\n    public var sectionKeyForValue: ((Row.Cell.Value) -> (String))?\n\n    /// A closure that returns header title for a section for particular key.\n    /// By default returns the key itself.\n    public var sectionHeaderTitleForKey: ((String) -> String?)? = { $0 }\n\n    /// A closure that returns footer title for a section for particular key.\n    public var sectionFooterTitleForKey: ((String) -> String?)?\n\n\n    public var optionsProviderRow: OptionsRow {\n        return row as! OptionsRow\n    }\n    \n\n    override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    }\n\n    convenience public init(_ callback: ((UIViewController) -> Void)?) {\n        self.init(nibName: nil, bundle: nil)\n        onDismissCallback = callback\n    }\n\n    public required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func viewDidLoad() {\n        super.viewDidLoad()\n        setupForm()\n    }\n\n    open func setupForm() {\n        optionsProviderRow.optionsProvider?.options(for: self) { [weak self] (options: [OptionsRow.OptionsProviderType.Option]?) in\n            guard let strongSelf = self, let options = options else { return }\n            strongSelf.optionsProviderRow.cachedOptionsData = options\n            strongSelf.setupForm(with: options)\n        }\n    }\n    \n    open func setupForm(with options: [OptionsRow.OptionsProviderType.Option]) {\n        if let optionsBySections = optionsBySections(with: options) {\n            for (sectionKey, options) in optionsBySections {\n                form +++ section(with: options,\n                                 header: sectionHeaderTitleForKey?(sectionKey),\n                                 footer: sectionFooterTitleForKey?(sectionKey))\n            }\n        } else {\n            form +++ section(with: options, header: row.title, footer: nil)\n        }\n    }\n    \n    open func optionsBySections(with options: [OptionsRow.OptionsProviderType.Option]) -> [(String, [Row.Cell.Value])]? {\n        guard let sectionKeyForValue = sectionKeyForValue else { return nil }\n\n        let sections = options.reduce([:]) { (reduced, option) -> [String: [Row.Cell.Value]] in\n            var reduced = reduced\n            let key = sectionKeyForValue(option)\n            var items = reduced[key] ?? []\n            items.append(option)\n            reduced[key] = items\n            return reduced\n        }\n\n        return sections.sorted(by: { (lhs, rhs) in lhs.0 < rhs.0 })\n    }\n\n    func section(with options: [OptionsRow.OptionsProviderType.Option], header: String?, footer: String?) -> SelectableSection<Row> {\n        let section = SelectableSection<Row>(header: header ?? \"\", footer: footer ?? \"\", selectionType: .multipleSelection) { section in\n            section.onSelectSelectableRow = {  [weak self] _, selectableRow in\n                var newValue: Set<OptionsRow.OptionsProviderType.Option> = self?.row.value ?? []\n                if let selectableValue = selectableRow.value {\n                    newValue.insert(selectableValue)\n                } else {\n                    newValue.remove(selectableRow.selectableValue!)\n                }\n                self?.row.value = newValue\n            }\n        }\n        for option in options {\n            section <<< Row.init { lrow in\n                lrow.title = String(describing: option)\n                lrow.selectableValue = option\n                lrow.value = self.row.value?.contains(option) ?? false ? option : nil\n                self.selectableRowSetup?(lrow)\n            }.cellSetup { [weak self] cell, row in\n                self?.selectableRowCellSetup?(cell, row)\n            }.cellUpdate { [weak self] cell, row in\n                self?.selectableRowCellUpdate?(cell, row)\n            }\n        }\n        return section\n    }\n}\n\nopen class MultipleSelectorViewController<OptionsRow: OptionsProviderRow>: _MultipleSelectorViewController<ListCheckRow<OptionsRow.OptionsProviderType.Option>, OptionsRow> where OptionsRow.OptionsProviderType.Option: Hashable{\n    \n    override public init(nibName nibNameOrNil: String? = nil, bundle nibBundleOrNil: Bundle? = nil) {\n        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    }\n    \n    public required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n    \n}\n"
  },
  {
    "path": "Source/Rows/Controllers/SelectorAlertController.swift",
    "content": "//  SelectorAlertController.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/// Specific type, Responsible for the options passed to a selector alert view controller\npublic protocol AlertOptionsProviderRow: OptionsProviderRow {\n\n    var cancelTitle: String? { get set }\n\n}\n\n/// Selector UIAlertController\nopen class SelectorAlertController<AlertOptionsRow: AlertOptionsProviderRow>: UIAlertController, TypedRowControllerType where AlertOptionsRow.OptionsProviderType.Option == AlertOptionsRow.Cell.Value, AlertOptionsRow: BaseRow {\n\n    /// The row that pushed or presented this controller\n    public var row: RowOf<AlertOptionsRow.Cell.Value>!\n\n    @available(*, deprecated, message: \"Use AlertOptionsRow.cancelTitle instead.\")\n    public var cancelTitle = NSLocalizedString(\"Cancel\", comment: \"\")\n\n    /// A closure to be called when the controller disappears.\n    public var onDismissCallback: ((UIViewController) -> Void)?\n    \n    /// Options provider to use to get available options.\n    /// If not set will use synchronous data provider built with `row.dataProvider.arrayData`.\n    //    public var optionsProvider: OptionsProvider<T>?\n    public var optionsProviderRow: AlertOptionsRow {\n        return row as Any as! AlertOptionsRow\n    }\n\n    override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    convenience public init(_ callback: ((UIViewController) -> Void)?) {\n        self.init()\n        onDismissCallback = callback\n    }\n\n    open override func viewDidLoad() {\n        super.viewDidLoad()\n        guard let options = optionsProviderRow.options else { return }\n        let cancelTitle = optionsProviderRow.cancelTitle ?? NSLocalizedString(\"Cancel\", comment: \"\")\n        addAction(UIAlertAction(title: cancelTitle, style: .cancel, handler: nil))\n        for option in options {\n            addAction(UIAlertAction(title: row.displayValueFor?(option), style: .default, handler: { [weak self] _ in\n                self?.row.value = option\n                self?.onDismissCallback?(self!)\n            }))\n        }\n    }\n\n}\n"
  },
  {
    "path": "Source/Rows/Controllers/SelectorViewController.swift",
    "content": "//  SelectorViewController.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n/**\n *  Responsible for the options passed to a selector view controller\n */\n\npublic protocol OptionsProviderRow: TypedRowType {\n    associatedtype OptionsProviderType: OptionsProviderConformance\n    \n    var optionsProvider: OptionsProviderType? { get set }\n    \n    var cachedOptionsData: [OptionsProviderType.Option]? { get set }\n}\n\nextension OptionsProviderRow where Self: BaseRow {\n    \n    public var options: [OptionsProviderType.Option]? {\n        set (newValue){\n            let optProvider = OptionsProviderType.init(array: newValue)\n            optionsProvider = optProvider\n        }\n        get {\n            return self.cachedOptionsData ?? optionsProvider?.optionsArray\n        }\n    }\n    \n    public var cachedOptionsData: [OptionsProviderType.Option]? {\n        get {\n            return self._cachedOptionsData as? [OptionsProviderType.Option]\n        }\n        set {\n            self._cachedOptionsData = newValue\n        }\n    }\n}\n\npublic protocol OptionsProviderConformance: ExpressibleByArrayLiteral {\n    associatedtype Option: Equatable\n    \n    init(array: [Option]?)\n    func options(for selectorViewController: FormViewController, completion: @escaping ([Option]?) -> Void)\n    var optionsArray: [Option]? { get }\n    \n}\n\n/// Provider of selectable options.\npublic enum OptionsProvider<T: Equatable>: OptionsProviderConformance {\n    \n    /// Synchronous provider that provides array of options it was initialized with\n    case array([T]?)\n    /// Provider that uses closure it was initialized with to provide options. Can be synchronous or asynchronous.\n    case lazy((FormViewController, @escaping ([T]?) -> Void) -> Void)\n    \n    public init(array: [T]?) {\n        self = .array(array)\n    }\n    \n    public init(arrayLiteral elements: T...) {\n        self = .array(elements)\n    }\n    \n    public func options(for selectorViewController: FormViewController, completion: @escaping ([T]?) -> Void) {\n        switch self {\n        case let .array(array):\n            completion(array)\n        case let .lazy(fetch):\n            fetch(selectorViewController, completion)\n        }\n    }\n    \n    public var optionsArray: [T]?{\n        switch self {\n        case let .array(arrayData):\n            return arrayData\n        default:\n            return nil\n        }\n    }\n}\n\nopen class _SelectorViewController<Row: SelectableRowType, OptionsRow: OptionsProviderRow>: FormViewController, TypedRowControllerType where Row: BaseRow, Row.Cell.Value == OptionsRow.OptionsProviderType.Option {\n\n    /// The row that pushed or presented this controller\n    public var row: RowOf<Row.Cell.Value>!\n    public var enableDeselection = true\n    public var dismissOnSelection = true\n    public var dismissOnChange = true\n\n    public var selectableRowSetup: ((_ row: Row) -> Void)?\n    public var selectableRowCellUpdate: ((_ cell: Row.Cell, _ row: Row) -> Void)?\n    public var selectableRowCellSetup: ((_ cell: Row.Cell, _ row: Row) -> Void)?\n\t\n    /// A closure to be called when the controller disappears.\n    public var onDismissCallback: ((UIViewController) -> Void)?\n\n    /// A closure that should return key for particular row value.\n    /// This key is later used to break options by sections.\n    public var sectionKeyForValue: ((Row.Cell.Value) -> (String))?\n\n    /// A closure that returns header title for a section for particular key.\n    /// By default returns the key itself.\n    public var sectionHeaderTitleForKey: ((String) -> String?)? = { $0 }\n\n    /// A closure that returns footer title for a section for particular key.\n    public var sectionFooterTitleForKey: ((String) -> String?)?\n    \n    public var optionsProviderRow: OptionsRow {\n        return row as! OptionsRow\n    }\n\n    override public init(style: UITableView.Style) {\n        super.init(style: style)\n    }\n\n    override public init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {\n        super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)\n    }\n\n    convenience public init(_ callback: ((UIViewController) -> Void)?) {\n        self.init(nibName: nil, bundle: nil)\n        onDismissCallback = callback\n    }\n\n    public required init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func viewDidLoad() {\n        super.viewDidLoad()\n        setupForm()\n    }\n\n    open func setupForm() {\n        let optProvider = optionsProviderRow.optionsProvider\n        optProvider?.options(for: self) { [weak self] (options: [Row.Cell.Value]?) in\n            guard let strongSelf = self, let options = options else { return }\n            strongSelf.optionsProviderRow.cachedOptionsData = options\n            strongSelf.setupForm(with: options)\n        }\n    }\n    \n    open func setupForm(with options: [Row.Cell.Value]) {\n        if let optionsBySections = optionsBySections(with: options) {\n            for (sectionKey, options) in optionsBySections {\n                form +++ section(with: options,\n                                 header: sectionHeaderTitleForKey?(sectionKey),\n                                 footer: sectionFooterTitleForKey?(sectionKey))\n            }\n        } else {\n            form +++ section(with: options, header: nil, footer: nil)\n        }\n    }\n    \n    func optionsBySections(with options: [Row.Cell.Value]) -> [(String, [Row.Cell.Value])]? {\n        guard let sectionKeyForValue = sectionKeyForValue else { return nil }\n\n        let sections = options.reduce([:]) { (reduced, option) -> [String: [Row.Cell.Value]] in\n            var reduced = reduced\n            let key = sectionKeyForValue(option)\n            reduced[key] = (reduced[key] ?? []) + [option]\n            return reduced\n        }\n\n        return sections.sorted(by: { (lhs, rhs) in lhs.0 < rhs.0 })\n    }\n\n    func section(with options: [Row.Cell.Value], header: String?, footer: String?) -> SelectableSection<Row> {\n        let section = SelectableSection<Row>(header: header, footer: footer, selectionType: .singleSelection(enableDeselection: enableDeselection)) { section in\n            section.onSelectSelectableRow = { [weak self] _, row in\n                let changed = self?.row.value != row.value\n                self?.row.value = row.value\n                \n                if let form = row.section?.form {\n                    for section in form where section !== row.section && section is SelectableSection<Row> {\n                        let section = section as Any as! SelectableSection<Row>\n                        if let selectedRow = section.selectedRow(), selectedRow !== row {\n                            selectedRow.value = nil\n                            selectedRow.updateCell()\n                        }\n                    }\n                }\n                \n                if self?.dismissOnSelection == true || (changed && self?.dismissOnChange == true) {\n                    self?.onDismissCallback?(self!)\n                }\n            }\n        }\n        for option in options {\n            section <<< Row.init(String(describing: option)) { lrow in\n                lrow.title = self.row.displayValueFor?(option)\n                lrow.selectableValue = option\n                lrow.value = self.row.value == option ? option : nil\n                self.selectableRowSetup?(lrow)\n            }.cellSetup { [weak self] cell, row in\n                self?.selectableRowCellSetup?(cell, row)\n            }.cellUpdate { [weak self] cell, row in\n                self?.selectableRowCellUpdate?(cell, row)\n            }\n        }\n        return section\n    }\n\n}\n\n/// Selector Controller (used to select one option among a list)\nopen class SelectorViewController<OptionsRow: OptionsProviderRow>: _SelectorViewController<ListCheckRow<OptionsRow.OptionsProviderType.Option>, OptionsRow> {\n}\n"
  },
  {
    "path": "Source/Rows/DateInlineRow.swift",
    "content": "//  DateInliuneRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nextension DatePickerRowProtocol {\n\n    func configureInlineRow(_ inlineRow: DatePickerRowProtocol) {\n        inlineRow.minimumDate = minimumDate\n        inlineRow.maximumDate = maximumDate\n        inlineRow.minuteInterval = minuteInterval\n    }\n    \n    func configurePickerStyle(_ cell: DatePickerCell, _ mode: UIDatePicker.Mode = .dateAndTime) {\n        cell.datePicker.datePickerMode = mode\n        // For Xcode 11.4 and above\n        #if swift(>=5.2)\n            if #available(iOS 14.0, *) {\n                #if swift(>=5.3) && !(os(OSX) || (os(iOS) && targetEnvironment(macCatalyst)))\n                    cell.datePicker.preferredDatePickerStyle = .inline\n                #else\n                    cell.datePicker.preferredDatePickerStyle = .wheels\n                #endif\n            }\n            else if #available(iOS 13.4, *) {\n                cell.datePicker.preferredDatePickerStyle = .wheels\n            }\n        #endif\n    }\n\n}\n\nopen class _DateInlineRow: _DateInlineFieldRow {\n\n    public typealias InlineRow = DatePickerRow\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter?.timeStyle = .none\n        dateFormatter?.dateStyle = .medium\n    }\n\n    open func setupInlineRow(_ inlineRow: DatePickerRow) {\n        configureInlineRow(inlineRow)\n        configurePickerStyle(inlineRow.cell, .date)\n    }\n}\n\nopen class _TimeInlineRow: _DateInlineFieldRow {\n\n    public typealias InlineRow = TimePickerRow\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter?.timeStyle = .short\n        dateFormatter?.dateStyle = .none\n    }\n\n    open func setupInlineRow(_ inlineRow: TimePickerRow) {\n        configureInlineRow(inlineRow)\n        configurePickerStyle(inlineRow.cell, .time)\n    }\n}\n\nopen class _DateTimeInlineRow: _DateInlineFieldRow {\n\n    public typealias InlineRow = DateTimePickerRow\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter?.timeStyle = .short\n        dateFormatter?.dateStyle = .short\n    }\n\n    open func setupInlineRow(_ inlineRow: DateTimePickerRow) {\n        configureInlineRow(inlineRow)\n        configurePickerStyle(inlineRow.cell)\n    }\n}\n\nopen class _CountDownInlineRow: _DateInlineFieldRow {\n\n    public typealias InlineRow = CountDownPickerRow\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = {\n            guard let date = $0 else {\n                return nil\n            }\n\n            let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: date)\n            return DateComponentsFormatter.localizedString(from: dateComponents, unitsStyle: .full)?.replacingOccurrences(of: \",\", with: \"\")\n        }\n    }\n\n    public func setupInlineRow(_ inlineRow: CountDownPickerRow) {\n        configureInlineRow(inlineRow)\n    }\n}\n\n/// A row with an Date as value where the user can select a date from an inline picker view.\npublic final class DateInlineRow_<T>: _DateInlineRow, RowType, InlineRowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n}\n\npublic typealias DateInlineRow = DateInlineRow_<Date>\n\n/// A row with an Date as value where the user can select date and time from an inline picker view.\npublic final class DateTimeInlineRow_<T>: _DateTimeInlineRow, RowType, InlineRowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n}\n\npublic typealias DateTimeInlineRow = DateTimeInlineRow_<Date>\n\n/// A row with an Date as value where the user can select a time from an inline picker view.\npublic final class TimeInlineRow_<T>: _TimeInlineRow, RowType, InlineRowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n}\n\npublic typealias TimeInlineRow = TimeInlineRow_<Date>\n\n///// A row with an Date as value where the user can select hour and minute as a countdown timer in an inline picker view.\npublic final class CountDownInlineRow_<T>: _CountDownInlineRow, RowType, InlineRowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n}\n\npublic typealias CountDownInlineRow = CountDownInlineRow_<Date>\n"
  },
  {
    "path": "Source/Rows/DatePickerRow.swift",
    "content": "//  DateRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class DatePickerCell: Cell<Date>, CellType {\n\n    @IBOutlet weak public var datePicker: UIDatePicker!\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        let datePicker = UIDatePicker()\n        self.datePicker = datePicker\n        self.datePicker.translatesAutoresizingMaskIntoConstraints = false\n\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n        self.contentView.addSubview(self.datePicker)\n        self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: \"V:|-0-[picker]-0-|\", options: [], metrics: nil, views: [\"picker\": self.datePicker!]))\n        self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: \"H:|-0-[picker]-0-|\", options: [], metrics: nil, views: [\"picker\": self.datePicker!]))\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        selectionStyle = .none\n        accessoryType = .none\n        editingAccessoryType =  .none\n        height = { UITableView.automaticDimension }\n        datePicker.datePickerMode = datePickerMode()\n        datePicker.addTarget(self, action: #selector(DatePickerCell.datePickerValueDidChange(_:)), for: .valueChanged)\n\n        if datePicker.datePickerMode != .countDownTimer {\n            #if swift(>=5.2)\n                if #available(iOS 14.0, *) {\n                    #if swift(>=5.3) && !(os(OSX) || (os(iOS) && targetEnvironment(macCatalyst)))\n                        datePicker.preferredDatePickerStyle = .inline\n                    #else\n                        datePicker.preferredDatePickerStyle = .wheels\n                    #endif\n                } else if #available(iOS 13.4, *) {\n                    datePicker.preferredDatePickerStyle = .wheels\n                }\n             #endif\n        }\n    }\n\n    deinit {\n        datePicker?.removeTarget(self, action: nil, for: .allEvents)\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n        datePicker.isUserInteractionEnabled = !row.isDisabled\n        detailTextLabel?.text = nil\n        textLabel?.text = nil\n        datePicker.setDate(row.value ?? Date(), animated: row is CountDownPickerRow)\n        datePicker.minimumDate = (row as? DatePickerRowProtocol)?.minimumDate\n        datePicker.maximumDate = (row as? DatePickerRowProtocol)?.maximumDate\n        if let minuteIntervalValue = (row as? DatePickerRowProtocol)?.minuteInterval {\n            datePicker.minuteInterval = minuteIntervalValue\n        }\n    }\n\n    @objc(datePickerValueDidChange:) func datePickerValueDidChange(_ sender: UIDatePicker) {\n        row?.value = sender.date\n        \n        // workaround for UIDatePicker bug when it doesn't trigger \"value changed\" event after trying to pick 00:00 value\n        // for details see this comment: https://stackoverflow.com/questions/20181980/uidatepicker-bug-uicontroleventvaluechanged-after-hitting-minimum-internal#comment56681891_20204225\n        if sender.datePickerMode == .countDownTimer && sender.countDownDuration == TimeInterval(sender.minuteInterval * 60) {\n            datePicker.countDownDuration = sender.countDownDuration\n        }\n        \n    }\n\n    private func datePickerMode() -> UIDatePicker.Mode {\n        switch row {\n        case is DatePickerRow:\n            return .date\n        case is TimePickerRow:\n            return .time\n        case is DateTimePickerRow:\n            return .dateAndTime\n        case is CountDownPickerRow:\n            return .countDownTimer\n        default:\n            return .date\n        }\n    }\n\n}\n\nopen class _DatePickerRow: Row<DatePickerCell>, DatePickerRowProtocol {\n\n    open var minimumDate: Date?\n    open var maximumDate: Date?\n    open var minuteInterval: Int?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n    }\n}\n\n/// A row with an Date as value where the user can select a date directly.\npublic final class DatePickerRow: _DatePickerRow, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select a time directly.\npublic final class TimePickerRow: _DatePickerRow, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select date and time directly.\npublic final class DateTimePickerRow: _DatePickerRow, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select hour and minute as a countdown timer.\npublic final class CountDownPickerRow: _DatePickerRow, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/DateRow.swift",
    "content": "//  DateRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\nimport Foundation\n\nopen class _DateRow: _DateFieldRow {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter = DateFormatter()\n        dateFormatter?.timeStyle = .none\n        dateFormatter?.dateStyle = .medium\n        dateFormatter?.locale = Locale.current\n    }\n}\n\nopen class _TimeRow: _DateFieldRow {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter = DateFormatter()\n        dateFormatter?.timeStyle = .short\n        dateFormatter?.dateStyle = .none\n        dateFormatter?.locale = Locale.current\n    }\n}\n\nopen class _DateTimeRow: _DateFieldRow {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        dateFormatter = DateFormatter()\n        dateFormatter?.timeStyle = .short\n        dateFormatter?.dateStyle = .short\n        dateFormatter?.locale = Locale.current\n    }\n}\n\nopen class _CountDownRow: _DateFieldRow {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = { [unowned self] value in\n            guard let val = value else {\n                return nil\n            }\n            if let formatter = self.dateFormatter {\n                return formatter.string(from: val)\n            }\n\n            let dateComponents = Calendar.current.dateComponents([.hour, .minute], from: val)\n            return DateComponentsFormatter.localizedString(from: dateComponents, unitsStyle: .full)?.replacingOccurrences(of: \",\", with: \"\")\n        }\n    }\n}\n\n/// A row with an Date as value where the user can select a date from a picker view.\npublic final class DateRow: _DateRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select a time from a picker view.\npublic final class TimeRow: _TimeRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select date and time from a picker view.\npublic final class DateTimeRow: _DateTimeRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with an Date as value where the user can select hour and minute as a countdown timer in a picker view.\npublic final class CountDownRow: _CountDownRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/DoublePickerInputRow.swift",
    "content": "//\n//  DoublePickerInputRow.swift\n//  Eureka\n//\n//  Created by Mathias Claassen on 5/10/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Foundation\nimport UIKit\n\nopen class DoublePickerInputCell<A, B> : _PickerInputCell<Tuple<A, B>> where A: Equatable, B: Equatable {\n\n    private var pickerRow: _DoublePickerInputRow<A, B>! { return row as? _DoublePickerInputRow<A, B> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        if let selectedValue = pickerRow.value, let indexA = pickerRow.firstOptions().firstIndex(of: selectedValue.a),\n            let indexB = pickerRow.secondOptions(selectedValue.a).firstIndex(of: selectedValue.b) {\n            picker.selectRow(indexA, inComponent: 0, animated: true)\n            picker.selectRow(indexB, inComponent: 1, animated: true)\n        }\n    }\n\n    open override func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 2\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        return  component == 0 ? pickerRow.firstOptions().count : pickerRow.secondOptions(pickerRow.selectedFirst()).count\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        if component == 0 {\n            return pickerRow.displayValueForFirstRow(pickerRow.firstOptions()[row])\n        } else {\n            return pickerRow.displayValueForSecondRow(pickerRow.secondOptions(pickerRow.selectedFirst())[row])\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {\n        if component == 0 {\n            let a = pickerRow.firstOptions()[row]\n            if let value = pickerRow.value {\n                guard value.a != a else {\n                    return\n                }\n                if pickerRow.secondOptions(a).contains(value.b) {\n                    pickerRow.value = Tuple(a: a, b: value.b)\n                    pickerView.reloadComponent(1)\n                    update()\n                    return\n                } else {\n                    pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[0])\n                }\n            } else {\n                pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[0])\n            }\n            pickerView.reloadComponent(1)\n            pickerView.selectRow(0, inComponent: 1, animated: true)\n        } else {\n            let a = pickerRow.selectedFirst()\n            pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[row])\n        }\n        update()\n    }\n}\n\nopen class _DoublePickerInputRow<A: Equatable, B: Equatable> : Row<DoublePickerInputCell<A, B>>, NoValueDisplayTextConformance {\n\n    open var noValueDisplayText: String? = nil\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = {_ in []}\n    \n    /// Modify the displayed values for the first picker row.\n    public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }\n    /// Modify the displayed values for the second picker row.\n    public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }\n    \n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    func selectedFirst() -> A {\n        return value?.a ?? firstOptions()[0]\n    }\n\n}\n\n/// A generic row where the user can pick an option from a picker view displayed in the keyboard area\npublic final class DoublePickerInputRow<A, B>: _DoublePickerInputRow<A, B>, RowType where A: Equatable, B: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        self.displayValueFor = { [weak self] tuple in\n            guard let tuple = tuple else {\n                return self?.noValueDisplayText\n            }\n            return String(describing: tuple.a) + \", \" + String(describing: tuple.b)\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Rows/DoublePickerRow.swift",
    "content": "//\n//  MultiplePickerRow.swift\n//  Eureka\n//\n//  Created by Mathias Claassen on 5/8/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Foundation\nimport UIKit\n\npublic struct Tuple<A: Equatable, B: Equatable> {\n    \n    public let a: A\n    public let b: B\n\n    public init(a: A, b: B) {\n        self.a = a\n        self.b = b\n    }\n\n}\n\nextension Tuple: Equatable {}\n\npublic func == <A: Equatable, B: Equatable>(lhs: Tuple<A, B>, rhs: Tuple<A, B>) -> Bool {\n    return lhs.a == rhs.a && lhs.b == rhs.b\n}\n\n// MARK: MultiplePickerCell\n\nopen class DoublePickerCell<A, B> : _PickerCell<Tuple<A, B>> where A: Equatable, B: Equatable {\n\n    private var pickerRow: _DoublePickerRow<A, B>? { return row as? _DoublePickerRow<A, B> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        if let selectedValue = pickerRow?.value, let indexA = pickerRow?.firstOptions().firstIndex(of: selectedValue.a),\n            let indexB = pickerRow?.secondOptions(selectedValue.a).firstIndex(of: selectedValue.b) {\n            picker.selectRow(indexA, inComponent: 0, animated: true)\n            picker.selectRow(indexB, inComponent: 1, animated: true)\n        }\n    }\n\n    open override func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 2\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        guard let pickerRow = pickerRow else { return 0 }\n        return component == 0 ? pickerRow.firstOptions().count : pickerRow.secondOptions(pickerRow.selectedFirst()).count\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        guard let pickerRow = pickerRow else { return \"\" }\n        if component == 0 {\n            return pickerRow.displayValueForFirstRow(pickerRow.firstOptions()[row])\n        } else {\n            return pickerRow.displayValueForSecondRow(pickerRow.secondOptions(pickerRow.selectedFirst())[row])\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {\n        guard let pickerRow = pickerRow else { return }\n        if component == 0 {\n            let a = pickerRow.firstOptions()[row]\n            if let value = pickerRow.value {\n                guard value.a != a else {\n                    return\n                }\n                if pickerRow.secondOptions(a).contains(value.b) {\n                    pickerRow.value = Tuple(a: a, b: value.b)\n                    pickerView.reloadComponent(1)\n                    return\n                } else {\n                    pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[0])\n                }\n            } else {\n                pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[0])\n            }\n            pickerView.reloadComponent(1)\n            pickerView.selectRow(0, inComponent: 1, animated: true)\n        } else {\n            let a = pickerRow.selectedFirst()\n            pickerRow.value = Tuple(a: a, b: pickerRow.secondOptions(a)[row])\n        }\n    }\n\n}\n\n// MARK: PickerRow\nopen class _DoublePickerRow<A, B> : Row<DoublePickerCell<A, B>> where A: Equatable, B: Equatable {\n\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = {_ in []}\n    \n    /// Modify the displayed values for the first picker row.\n    public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }\n    /// Modify the displayed values for the second picker row.\n    public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    func selectedFirst() -> A {\n        return value?.a ?? firstOptions()[0]\n    }\n\n}\n\n/// A generic row where the user can pick an option from a picker view\npublic final class DoublePickerRow<A, B>: _DoublePickerRow<A, B>, RowType where A: Equatable, B: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n}\n"
  },
  {
    "path": "Source/Rows/FieldsRow.swift",
    "content": "//  FieldsRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class TextCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .default\n        textField.autocapitalizationType = .sentences\n        textField.keyboardType = .default\n    }\n}\n\nopen class IntCell: _FieldCell<Int>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .default\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .numberPad\n    }\n}\n\nopen class PhoneCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.keyboardType = .phonePad\n        if #available(iOS 10,*) {\n            textField.textContentType = .telephoneNumber\n        }\n    }\n}\n\nopen class NameCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .words\n        textField.keyboardType = .asciiCapable\n        if #available(iOS 10,*) {\n            textField.textContentType = .name\n        }\n    }\n}\n\nopen class EmailCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .emailAddress\n        if #available(iOS 10,*) {\n            textField.textContentType = .emailAddress\n        }\n    }\n}\n\nopen class PasswordCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .asciiCapable\n        textField.isSecureTextEntry = true\n        if let textLabel = textLabel {\n            textField.setContentHuggingPriority(textLabel.contentHuggingPriority(for: .horizontal) - 1, for: .horizontal)\n        }\n        if #available(iOS 11,*) {\n            textField.textContentType = .password\n        }\n    }\n}\n\nopen class DecimalCell: _FieldCell<Double>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.keyboardType = .decimalPad\n    }\n}\n\nopen class URLCell: _FieldCell<URL>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .URL\n        if #available(iOS 10,*) {\n            textField.textContentType = .URL\n        }\n    }\n}\n\nopen class TwitterCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .twitter\n    }\n}\n\nopen class AccountCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .none\n        textField.keyboardType = .asciiCapable\n        if #available(iOS 11,*) {\n            textField.textContentType = .username\n        }\n    }\n}\n\nopen class ZipCodeCell: _FieldCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        textField.autocorrectionType = .no\n        textField.autocapitalizationType = .allCharacters\n        textField.keyboardType = .numbersAndPunctuation\n        if #available(iOS 10,*) {\n            textField.textContentType = .postalCode\n        }\n    }\n}\n\nopen class _TextRow: FieldRow<TextCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _IntRow: FieldRow<IntCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        let numberFormatter = NumberFormatter()\n        numberFormatter.locale = Locale.current\n        numberFormatter.numberStyle = .decimal\n        numberFormatter.minimumFractionDigits = 0\n        formatter = numberFormatter\n    }\n}\n\nopen class _PhoneRow: FieldRow<PhoneCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _NameRow: FieldRow<NameCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _EmailRow: FieldRow<EmailCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _PasswordRow: FieldRow<PasswordCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _DecimalRow: FieldRow<DecimalCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        let numberFormatter = NumberFormatter()\n        numberFormatter.locale = Locale.current\n        numberFormatter.numberStyle = .decimal\n        numberFormatter.minimumFractionDigits = 2\n        formatter = numberFormatter\n    }\n}\n\nopen class _URLRow: FieldRow<URLCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _TwitterRow: FieldRow<TwitterCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _AccountRow: FieldRow<AccountCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _ZipCodeRow: FieldRow<ZipCodeCell> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter arbitrary text.\npublic final class TextRow: _TextRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter names. Biggest difference to TextRow is that it autocapitalization is set to Words.\npublic final class NameRow: _NameRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter secure text.\npublic final class PasswordRow: _PasswordRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter an email address.\npublic final class EmailRow: _EmailRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter a twitter username.\npublic final class TwitterRow: _TwitterRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter a simple account username.\npublic final class AccountRow: _AccountRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter a zip code.\npublic final class ZipCodeRow: _ZipCodeRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row where the user can enter an integer number.\npublic final class IntRow: _IntRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row where the user can enter a decimal number.\npublic final class DecimalRow: _DecimalRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row where the user can enter an URL. The value of this row will be a URL.\npublic final class URLRow: _URLRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A String valued row where the user can enter a phone number.\npublic final class PhoneRow: _PhoneRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/LabelRow.swift",
    "content": "//  LabelRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: LabelCell\n\nopen class LabelCellOf<T: Equatable>: Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        selectionStyle = .none\n    }\n}\n\npublic typealias LabelCell = LabelCellOf<String>\n\n// MARK: LabelRow\n\nopen class _LabelRow: Row<LabelCell> {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// Simple row that can show title and value but is not editable by user.\npublic final class LabelRow: _LabelRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/MultipleSelectorRow.swift",
    "content": "//  MultipleSelectorRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\nopen class _MultipleSelectorRow<T, Cell: CellType>: GenericMultipleSelectorRow<T, Cell> where Cell: BaseCell, Cell.Value == Set<T> {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A selector row where the user can pick several options from a pushed view controller\npublic final class MultipleSelectorRow<T: Hashable> : _MultipleSelectorRow<T, PushSelectorCell<Set<T>>>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/PickerInlineRow.swift",
    "content": "//  PickerInlineRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class PickerInlineCell<T: Equatable> : Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .none\n        editingAccessoryType =  .none\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n}\n\n// MARK: PickerInlineRow\n\nopen class _PickerInlineRow<T> : Row<PickerInlineCell<T>>, NoValueDisplayTextConformance where T: Equatable {\n\n    public typealias InlineRow = PickerRow<T>\n    open var options = [T]()\n    open var noValueDisplayText: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A generic inline row where the user can pick an option from a picker view which shows and hides itself automatically\npublic final class PickerInlineRow<T> : _PickerInlineRow<T>, RowType, InlineRowType where T: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n\n    public func setupInlineRow(_ inlineRow: InlineRow) {\n        inlineRow.options = self.options\n        inlineRow.displayValueFor = self.displayValueFor\n        inlineRow.cell.height = { UITableView.automaticDimension }\n    }\n}\n\nopen class _DoublePickerInlineRow<A, B> : Row<PickerInlineCell<Tuple<A, B>>>, NoValueDisplayTextConformance where A: Equatable, B: Equatable {\n\n    public typealias InlineRow = DoublePickerRow<A, B>\n\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = { _ in [] }\n\n    /// Modify the displayed values for the first picker row.\n    public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }\n\n    /// Modify the displayed values for the second picker row.\n    public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }\n    \n    public var noValueDisplayText: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        self.displayValueFor = { [weak self] tuple in\n            if let tuple = tuple {\n                return String(describing: tuple.a) + \", \" + String(describing: tuple.b)\n            }\n            return self?.noValueDisplayText\n        }\n    }\n}\n\n/// A generic inline row where the user can pick an option from a picker view which shows and hides itself automatically\npublic final class DoublePickerInlineRow<A, B> : _DoublePickerInlineRow<A, B>, RowType, InlineRowType where A: Equatable, B: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n\n    public func setupInlineRow(_ inlineRow: InlineRow) {\n        inlineRow.firstOptions = firstOptions\n        inlineRow.secondOptions = secondOptions\n        inlineRow.displayValueForFirstRow = displayValueForFirstRow\n        inlineRow.displayValueForSecondRow = displayValueForSecondRow\n        inlineRow.displayValueFor = self.displayValueFor\n        inlineRow.cell.height = { UITableView.automaticDimension }\n    }\n}\n\nopen class _TriplePickerInlineRow<A, B, C> : Row<PickerInlineCell<Tuple3<A, B, C>>>, NoValueDisplayTextConformance\n    where A: Equatable, B: Equatable, C: Equatable {\n\n    public typealias InlineRow = TriplePickerRow<A, B, C>\n\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = { _ in [] }\n    /// Options for third component given the selected value from the first and second components. Will be called often so should be O(1)\n    public var thirdOptions: ((A, B) -> [C]) = {_, _ in []}\n\n    open var noValueDisplayText: String?\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        self.displayValueFor = { [weak self] tuple in\n            if let tuple = tuple {\n                return String(describing: tuple.a) + \", \" + String(describing: tuple.b) + \", \" + String(describing: tuple.c)\n            }\n            return self?.noValueDisplayText\n        }\n    }\n}\n\n/// A generic inline row where the user can pick an option from a picker view which shows and hides itself automatically\npublic final class TriplePickerInlineRow<A, B, C> : _TriplePickerInlineRow<A, B, C>, RowType, InlineRowType\n    where A: Equatable, B: Equatable, C: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        onExpandInlineRow { cell, row, _ in\n            let color = cell.detailTextLabel?.textColor\n            row.onCollapseInlineRow { cell, _, _ in\n                cell.detailTextLabel?.textColor = color\n            }\n            cell.detailTextLabel?.textColor = cell.tintColor\n        }\n    }\n\n    public override func customDidSelect() {\n        super.customDidSelect()\n        if !isDisabled {\n            toggleInlineRow()\n        }\n    }\n\n    public func setupInlineRow(_ inlineRow: InlineRow) {\n        inlineRow.firstOptions = firstOptions\n        inlineRow.secondOptions = secondOptions\n        inlineRow.thirdOptions = thirdOptions\n        inlineRow.displayValueFor = self.displayValueFor\n        inlineRow.cell.height = { UITableView.automaticDimension }\n    }\n}\n"
  },
  {
    "path": "Source/Rows/PickerInputRow.swift",
    "content": "//  PickerInputRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: PickerInputCell\n\nopen class _PickerInputCell<T> : Cell<T>, CellType, UIPickerViewDataSource, UIPickerViewDelegate where T: Equatable {\n\n    lazy public var picker: UIPickerView = {\n        let picker = UIPickerView()\n        picker.translatesAutoresizingMaskIntoConstraints = false\n        return picker\n    }()\n\n    fileprivate var pickerInputRow: _PickerInputRow<T>? { return row as? _PickerInputRow<T> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .none\n        editingAccessoryType = .none\n        picker.delegate = self\n        picker.dataSource = self\n    }\n\n    deinit {\n        picker.delegate = nil\n        picker.dataSource = nil\n    }\n\n    open override func update() {\n        super.update()\n        selectionStyle = row.isDisabled ? .none : .default\n\n        if row.title?.isEmpty == false {\n            detailTextLabel?.text = row.displayValueFor?(row.value) ?? (row as? NoValueDisplayTextConformance)?.noValueDisplayText\n        } else {\n            textLabel?.text = row.displayValueFor?(row.value) ?? (row as? NoValueDisplayTextConformance)?.noValueDisplayText\n            detailTextLabel?.text = nil\n        }\n\n        if #available(iOS 13.0, *) {\n            textLabel?.textColor = row.isDisabled ? .tertiaryLabel : .label\n        } else {\n            textLabel?.textColor = row.isDisabled ? .gray : .black\n        }\n        if row.isHighlighted {\n            textLabel?.textColor = tintColor\n        }\n\n        picker.reloadAllComponents()\n    }\n\n    open override func didSelect() {\n        super.didSelect()\n        row.deselect()\n    }\n\n    open override var inputView: UIView? {\n        return picker\n    }\n\n    open override func cellCanBecomeFirstResponder() -> Bool {\n        return canBecomeFirstResponder\n    }\n\n    override open var canBecomeFirstResponder: Bool {\n        return !row.isDisabled\n    }\n\n    open func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 1\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        return pickerInputRow?.options.count ?? 0\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        return pickerInputRow?.displayValueFor?(pickerInputRow?.options[row])\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, didSelectRow rowNumber: Int, inComponent component: Int) {\n        if let picker = pickerInputRow, picker.options.count > rowNumber {\n            picker.value = picker.options[rowNumber]\n            update()\n        }\n    }\n}\n\nopen class PickerInputCell<T>: _PickerInputCell<T> where T: Equatable {\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n    \n    open override func update() {\n        super.update()\n        if let selectedValue = pickerInputRow?.value, let index = pickerInputRow?.options.firstIndex(of: selectedValue) {\n            picker.selectRow(index, inComponent: 0, animated: true)\n        }\n    }\n\n}\n\n// MARK: PickerInputRow\n\nopen class _PickerInputRow<T> : Row<PickerInputCell<T>>, NoValueDisplayTextConformance where T: Equatable {\n    open var noValueDisplayText: String? = nil\n\n    open var options = [T]()\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n\n    }\n}\n\n/// A generic row where the user can pick an option from a picker view displayed in the keyboard area\npublic final class PickerInputRow<T>: _PickerInputRow<T>, RowType where T: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/PickerRow.swift",
    "content": "//  PickerRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: PickerCell\n\nopen class _PickerCell<T> : Cell<T>, CellType, UIPickerViewDataSource, UIPickerViewDelegate where T: Equatable {\n\n    @IBOutlet public weak var picker: UIPickerView!\n\n    fileprivate var pickerRow: _PickerRow<T>? { return row as? _PickerRow<T> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        let pickerView = UIPickerView()\n        self.picker = pickerView\n        self.picker?.translatesAutoresizingMaskIntoConstraints = false\n\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n        self.contentView.addSubview(pickerView)\n        self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: \"V:|-0-[picker]-0-|\", options: [], metrics: nil, views: [\"picker\": pickerView]))\n        self.contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: \"H:|-0-[picker]-0-|\", options: [], metrics: nil, views: [\"picker\": pickerView]))\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType = .none\n        editingAccessoryType = .none\n        height = { UITableView.automaticDimension }\n        picker.delegate = self\n        picker.dataSource = self\n    }\n\n    open override func update() {\n        super.update()\n        textLabel?.text = nil\n        detailTextLabel?.text = nil\n        picker.reloadAllComponents()\n    }\n\n    deinit {\n        picker?.delegate = nil\n        picker?.dataSource = nil\n    }\n\n    open var pickerTextAttributes: [NSAttributedString.Key: Any]?\n\n    open func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 1\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        return pickerRow?.options.count ?? 0\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        return pickerRow?.displayValueFor?(pickerRow?.options[row])\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {\n        if let picker = pickerRow, !picker.options.isEmpty {\n            picker.value = picker.options[row]\n        }\n    }\n\n    open func pickerView(_ pickerView: UIPickerView, attributedTitleForRow row: Int, forComponent component: Int) -> NSAttributedString? {\n        guard let pickerTextAttributes = pickerTextAttributes, let text = self.pickerView(pickerView, titleForRow: row, forComponent: component) else {\n            return nil\n        }\n        return NSAttributedString(string: text, attributes: pickerTextAttributes)\n    }\n}\n\nopen class PickerCell<T> : _PickerCell<T> where T: Equatable {\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    open override func update() {\n        super.update()\n        if let selectedValue = pickerRow?.value, let index = pickerRow?.options.firstIndex(of: selectedValue) {\n            picker.selectRow(index, inComponent: 0, animated: true)\n        }\n    }\n\n}\n\n// MARK: PickerRow\n\nopen class _PickerRow<T> : Row<PickerCell<T>> where T: Equatable {\n\n    open var options = [T]()\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A generic row where the user can pick an option from a picker view\npublic final class PickerRow<T>: _PickerRow<T>, RowType where T: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/PopoverSelectorRow.swift",
    "content": "//  PopoverSelectorRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class _PopoverSelectorRow<Cell: CellType> : SelectorRow<Cell> where Cell: BaseCell {\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        onPresentCallback = { [weak self] (_, viewController) -> Void in\n            guard let porpoverController = viewController.popoverPresentationController, let tableView = self?.baseCell.formViewController()?.tableView, let cell = self?.cell else {\n                fatalError()\n            }\n            porpoverController.sourceView = tableView\n            porpoverController.sourceRect = tableView.convert(cell.detailTextLabel?.frame ?? cell.textLabel?.frame ?? cell.contentView.frame, from: cell)\n        }\n        presentationMode = .popover(controllerProvider: ControllerProvider.callback { return SelectorViewController<SelectorRow<Cell>> { _ in } }, onDismiss: { [weak self] in\n            $0.dismiss(animated: true)\n            self?.reload()\n        })\n    }\n\n    open override func didSelect() {\n        deselect()\n        super.didSelect()\n    }\n}\n\npublic final class PopoverSelectorRow<T: Equatable> : _PopoverSelectorRow<PushSelectorCell<T>>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/PushRow.swift",
    "content": "//  PushRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class _PushRow<Cell: CellType>: SelectorRow<Cell> where Cell: BaseCell {\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n        presentationMode = .show(controllerProvider: ControllerProvider.callback { return SelectorViewController<SelectorRow<Cell>> { _ in } }, onDismiss: { vc in\n            let _ = vc.navigationController?.popViewController(animated: true) })\n    }\n}\n\n/// A selector row where the user can pick an option from a pushed view controller\npublic final class PushRow<T: Equatable> : _PushRow<PushSelectorCell<T>>, RowType {\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/SegmentedRow.swift",
    "content": "//  SegmentedRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: SegmentedCell\n\nopen class SegmentedCell<T: Equatable> : Cell<T>, CellType {\n\n    @IBOutlet public weak var segmentedControl: UISegmentedControl!\n    @IBOutlet public weak var titleLabel: UILabel?\n\n    private var dynamicConstraints = [NSLayoutConstraint]()\n    fileprivate var observingTitleText = false\n    private var awakeFromNibCalled = false\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n        let segmentedControl = UISegmentedControl()\n        segmentedControl.translatesAutoresizingMaskIntoConstraints = false\n        segmentedControl.setContentHuggingPriority(UILayoutPriority(rawValue: 250), for: .horizontal)\n        self.segmentedControl = segmentedControl\n\n        self.titleLabel = self.textLabel\n        self.titleLabel?.translatesAutoresizingMaskIntoConstraints = false\n        self.titleLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n        self.titleLabel?.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)\n\n        NotificationCenter.default.addObserver(forName: UIApplication.willResignActiveNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            guard me.observingTitleText else { return }\n            me.titleLabel?.removeObserver(me, forKeyPath: \"text\")\n            me.observingTitleText = false\n        }\n        NotificationCenter.default.addObserver(forName: UIApplication.didBecomeActiveNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            guard !me.observingTitleText else { return }\n            me.titleLabel?.addObserver(me, forKeyPath: \"text\", options: [.new, .old], context: nil)\n            me.observingTitleText = true\n        }\n\n        NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: nil) { [weak self] _ in\n            self?.titleLabel = self?.textLabel\n            self?.setNeedsUpdateConstraints()\n        }\n        contentView.addSubview(titleLabel!)\n        contentView.addSubview(segmentedControl)\n        titleLabel?.addObserver(self, forKeyPath: \"text\", options: [.old, .new], context: nil)\n        observingTitleText = true\n        imageView?.addObserver(self, forKeyPath: \"image\", options: [.old, .new], context: nil)\n\n        contentView.addConstraint(NSLayoutConstraint(item: segmentedControl, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0))\n\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func awakeFromNib() {\n        super.awakeFromNib()\n        awakeFromNibCalled = true\n    }\n\n    deinit {\n        segmentedControl.removeTarget(self, action: nil, for: .allEvents)\n        if !awakeFromNibCalled {\n            if observingTitleText {\n                titleLabel?.removeObserver(self, forKeyPath: \"text\")\n            }\n            imageView?.removeObserver(self, forKeyPath: \"image\")\n            NotificationCenter.default.removeObserver(self, name: UIApplication.willResignActiveNotification, object: nil)\n            NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil)\n            NotificationCenter.default.removeObserver(self, name: UIContentSizeCategory.didChangeNotification, object: nil)\n        }\n\n    }\n\n    open override func setup() {\n        super.setup()\n        selectionStyle = .none\n        segmentedControl.addTarget(self, action: #selector(SegmentedCell.valueChanged), for: .valueChanged)\n    }\n\n    open override func update() {\n        super.update()\n        detailTextLabel?.text = nil\n\n        updateSegmentedControl()\n        segmentedControl.selectedSegmentIndex = selectedIndex() ?? UISegmentedControl.noSegment\n        segmentedControl.isEnabled = !row.isDisabled\n    }\n\n    @objc (segmentedValueDidChange) func valueChanged() {\n        row.value = (row as! OptionsRow<Self>).options?[segmentedControl.selectedSegmentIndex]\n    }\n\n    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n        let obj = object as AnyObject?\n\n        if let changeType = change, let _ = keyPath, ((obj === titleLabel && keyPath == \"text\") || (obj === imageView && keyPath == \"image\")) &&\n            (changeType[NSKeyValueChangeKey.kindKey] as? NSNumber)?.uintValue == NSKeyValueChange.setting.rawValue, !awakeFromNibCalled {\n            setNeedsUpdateConstraints()\n            updateConstraintsIfNeeded()\n        }\n    }\n\n    func updateSegmentedControl() {\n        segmentedControl.removeAllSegments()\n\n        (row as! OptionsRow<Self>).options?.reversed().forEach {\n            if let image = $0 as? UIImage {\n                segmentedControl.insertSegment(with: image, at: 0, animated: false)\n            } else {\n                segmentedControl.insertSegment(withTitle: row.displayValueFor?($0) ?? \"\", at: 0, animated: false)\n            }\n        }\n    }\n\n    open override func updateConstraints() {\n        guard !awakeFromNibCalled else {\n            super.updateConstraints()\n            return\n        }\n        contentView.removeConstraints(dynamicConstraints)\n        dynamicConstraints = []\n        var views: [String: AnyObject] =  [\"segmentedControl\": segmentedControl]\n\n        var hasImageView = false\n        var hasTitleLabel = false\n\n        if let imageView = imageView, let _ = imageView.image {\n            views[\"imageView\"] = imageView\n            hasImageView = true\n        }\n\n        if let titleLabel = titleLabel, let text = titleLabel.text, !text.isEmpty {\n            views[\"titleLabel\"] = titleLabel\n            hasTitleLabel = true\n            dynamicConstraints.append(NSLayoutConstraint(item: titleLabel, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0))\n        }\n\n        dynamicConstraints.append(NSLayoutConstraint(item: segmentedControl!, attribute: .width, relatedBy: .greaterThanOrEqual, toItem: contentView, attribute: .width, multiplier: 0.3, constant: 0.0))\n\n        if hasImageView && hasTitleLabel {\n            dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[titleLabel]-[segmentedControl]-|\", options: [], metrics: nil, views: views)\n        } else if hasImageView && !hasTitleLabel {\n            dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-[segmentedControl]-|\", options: [], metrics: nil, views: views)\n        } else if !hasImageView && hasTitleLabel {\n            dynamicConstraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[titleLabel]-[segmentedControl]-|\", options: .alignAllCenterY, metrics: nil, views: views)\n        } else {\n            dynamicConstraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[segmentedControl]-|\", options: .alignAllCenterY, metrics: nil, views: views)\n        }\n        contentView.addConstraints(dynamicConstraints)\n        super.updateConstraints()\n    }\n\n    func selectedIndex() -> Int? {\n        guard let value = row.value else { return nil }\n        return (row as! OptionsRow<Self>).options?.firstIndex(of: value)\n    }\n}\n\n// MARK: SegmentedRow\n\n/// An options row where the user can select an option from an UISegmentedControl\npublic final class SegmentedRow<T: Equatable>: OptionsRow<SegmentedCell<T>>, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/SelectableRows/ListCheckRow.swift",
    "content": "//  ListCheckRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\nopen class ListCheckCell<T: Equatable> : Cell<T>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        accessoryType = row.value != nil ? .checkmark : .none\n        editingAccessoryType = accessoryType\n        selectionStyle = .default\n        if row.isDisabled {\n            tintAdjustmentMode = .dimmed\n            selectionStyle = .none\n        } else {\n            tintAdjustmentMode = .automatic\n        }\n    }\n\n    open override func setup() {\n        super.setup()\n        accessoryType =  .checkmark\n        editingAccessoryType = accessoryType\n    }\n\n    open override func didSelect() {\n        row.deselect()\n        row.updateCell()\n    }\n\n}\n\npublic final class ListCheckRow<T>: Row<ListCheckCell<T>>, SelectableRowType, RowType where T: Equatable {\n    public var selectableValue: T?\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n    }\n}\n"
  },
  {
    "path": "Source/Rows/SliderRow.swift",
    "content": "//  SliderRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport UIKit\n\n/// The cell of the SliderRow\nopen class SliderCell: Cell<Float>, CellType {\n\n    private var awakeFromNibCalled = false\n\n    @IBOutlet open weak var titleLabel: UILabel!\n    @IBOutlet open weak var valueLabel: UILabel!\n    @IBOutlet open weak var slider: UISlider!\n\n    open var formatter: NumberFormatter?\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: .value1, reuseIdentifier: reuseIdentifier)\n\n        NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            if me.shouldShowTitle {\n                me.titleLabel = me.textLabel\n                me.valueLabel = me.detailTextLabel\n                me.setNeedsUpdateConstraints()\n            }\n        }\n    }\n\n    deinit {\n        guard !awakeFromNibCalled else { return }\n        NotificationCenter.default.removeObserver(self, name: UIContentSizeCategory.didChangeNotification, object: nil)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n        awakeFromNibCalled = true\n    }\n\n    open override func setup() {\n        super.setup()\n        if !awakeFromNibCalled {\n            let title = textLabel\n            textLabel?.translatesAutoresizingMaskIntoConstraints = false\n            textLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n            self.titleLabel = title\n\n            let value = detailTextLabel\n            value?.translatesAutoresizingMaskIntoConstraints = false\n            value?.setContentHuggingPriority(UILayoutPriority(500), for: .horizontal)\n            value?.adjustsFontSizeToFitWidth = true\n            value?.minimumScaleFactor = 0.5\n            self.valueLabel = value\n\n            let slider = UISlider()\n            slider.translatesAutoresizingMaskIntoConstraints = false\n            slider.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n            self.slider = slider\n\n            if shouldShowTitle {\n                contentView.addSubview(titleLabel)\n            }\n\n            if !sliderRow.shouldHideValue {\n              contentView.addSubview(valueLabel)\n            }\n            contentView.addSubview(slider)\n            setNeedsUpdateConstraints()\n        }\n        selectionStyle = .none\n        slider.minimumValue = 0\n        slider.maximumValue = 10\n        slider.addTarget(self, action: #selector(SliderCell.valueChanged), for: .valueChanged)\n    }\n\n    open override func update() {\n        super.update()\n        titleLabel.text = row.title\n        titleLabel.isHidden = !shouldShowTitle\n        valueLabel.text = row.displayValueFor?(row.value ?? slider.minimumValue)\n        valueLabel.isHidden = sliderRow.shouldHideValue\n        slider.value = row.value ?? slider.minimumValue\n        slider.isEnabled = !row.isDisabled\n    }\n\n    @objc (sliderValueDidChange) func valueChanged() {\n        let roundedValue: Float\n        let steps = Float(sliderRow.steps)\n        if steps > 0 {\n            let stepValue = round((slider.value - slider.minimumValue) / (slider.maximumValue - slider.minimumValue) * steps)\n            let stepAmount = (slider.maximumValue - slider.minimumValue) / steps\n            roundedValue = stepValue * stepAmount + self.slider.minimumValue\n        } else {\n            roundedValue = slider.value\n        }\n        row.value = roundedValue\n        row.updateCell()\n    }\n\n    var shouldShowTitle: Bool {\n        return row?.title?.isEmpty == false\n    }\n\n    private var sliderRow: SliderRow {\n        return row as! SliderRow\n    }\n    \n    open override func updateConstraints() {\n        customConstraints()\n        super.updateConstraints()\n    }\n    \n    open var dynamicConstraints = [NSLayoutConstraint]()\n    \n    open func customConstraints() {\n        guard !awakeFromNibCalled else { return }\n        contentView.removeConstraints(dynamicConstraints)\n        dynamicConstraints = []\n        \n        var views: [String : Any] = [\"titleLabel\": titleLabel!, \"slider\": slider!, \"valueLabel\": valueLabel!]\n        let metrics = [\"spacing\": 15.0]\n        valueLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)\n        titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)\n        \n        let title = shouldShowTitle ? \"[titleLabel]-spacing-\" : \"\"\n        let value = !sliderRow.shouldHideValue ? \"-[valueLabel]\" : \"\"\n        \n        if let imageView = imageView, let _ = imageView.image {\n            views[\"imageView\"] = imageView\n            let hContraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[imageView]-(15)-\\(title)[slider]\\(value)-|\", options: .alignAllCenterY, metrics: metrics, views: views)\n            imageView.translatesAutoresizingMaskIntoConstraints = false\n            dynamicConstraints.append(contentsOf: hContraints)\n        } else {\n            let hContraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-\\(title)[slider]\\(value)-|\", options: .alignAllCenterY, metrics: metrics, views: views)\n            dynamicConstraints.append(contentsOf: hContraints)\n        }\n        let vContraint = NSLayoutConstraint(item: slider!, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0)\n        dynamicConstraints.append(vContraint)\n        contentView.addConstraints(dynamicConstraints)\n    }\n\n}\n        \n\n/// A row that displays a UISlider. If there is a title set then the title and value will appear above the UISlider.\npublic final class SliderRow: Row<SliderCell>, RowType {\n\n    public var steps: UInt = 20\n    public var shouldHideValue = false\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/StepperRow.swift",
    "content": "//\n//  StepperRow.swift\n//  Eureka\n//\n//  Created by Andrew Holt on 3/4/16.\n//  Copyright © 2016 Xmartlabs. All rights reserved.\n//\n\nimport UIKit\n\n// MARK: StepperCell\n\nopen class StepperCell: Cell<Double>, CellType {\n  \n  \n    @IBOutlet open weak var stepper: UIStepper!\n    @IBOutlet open weak var valueLabel: UILabel!\n    @IBOutlet open weak var titleLabel: UILabel!\n\n    private var awakeFromNibCalled = false\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: .value1, reuseIdentifier: reuseIdentifier)\n      \n        NotificationCenter.default.addObserver(forName: UIContentSizeCategory.didChangeNotification, object: nil, queue: nil) { [weak self] _ in\n            guard let me = self else { return }\n            if me.shouldShowTitle {\n                me.titleLabel = me.textLabel\n                me.setNeedsUpdateConstraints()\n            }\n        }\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n        awakeFromNibCalled = true\n    }\n\n    open override func setup() {\n        super.setup()\n        if !awakeFromNibCalled {\n            let title = textLabel\n            textLabel?.translatesAutoresizingMaskIntoConstraints = false\n            textLabel?.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n            self.titleLabel = title\n         \n            let stepper = UIStepper()\n            stepper.translatesAutoresizingMaskIntoConstraints = false\n            stepper.setContentHuggingPriority(UILayoutPriority(rawValue: 500), for: .horizontal)\n            self.stepper = stepper\n          \n            if shouldShowTitle {\n                contentView.addSubview(titleLabel)\n            }\n\n            setupValueLabel()\n            contentView.addSubview(stepper)\n            setNeedsUpdateConstraints()\n        }\n        selectionStyle = .none\n        stepper.addTarget(self, action: #selector(StepperCell.valueChanged), for: .valueChanged)\n    }\n\n    open func setupValueLabel() {\n        let label = UILabel()\n        label.translatesAutoresizingMaskIntoConstraints = false\n        label.setContentHuggingPriority(UILayoutPriority(500), for: .horizontal)\n        label.adjustsFontSizeToFitWidth = true\n        label.minimumScaleFactor = 0.5\n        self.valueLabel = label\n        contentView.addSubview(valueLabel)\n    }\n  \n    open override func update() {\n        super.update()\n        detailTextLabel?.text = nil\n        stepper.isEnabled = !row.isDisabled\n        \n        titleLabel.isHidden = !shouldShowTitle\n        stepper.value = row.value ?? 0\n        stepper.alpha = row.isDisabled ? 0.3 : 1.0\n        valueLabel?.textColor = tintColor\n        valueLabel?.alpha = row.isDisabled ? 0.3 : 1.0\n        valueLabel?.text = row.displayValueFor?(row.value)\n    }\n\n    @objc(stepperValueDidChange) func valueChanged() {\n        row.value = stepper.value\n        row.updateCell()\n    }\n  \n    var shouldShowTitle: Bool {\n        return row?.title?.isEmpty == false\n    }\n  \n    private var stepperRow: StepperRow {\n        return row as! StepperRow\n    }\n    \n    deinit {\n        stepper.removeTarget(self, action: nil, for: .allEvents)\n        guard !awakeFromNibCalled else { return }\n        NotificationCenter.default.removeObserver(self, name: UIContentSizeCategory.didChangeNotification, object: nil)\n    }\n\n    open override func updateConstraints() {\n        customConstraints()\n        super.updateConstraints()\n    }\n  \n    open var dynamicConstraints = [NSLayoutConstraint]()\n  \n    open func customConstraints() {\n        guard !awakeFromNibCalled else { return }\n        contentView.removeConstraints(dynamicConstraints)\n        dynamicConstraints = []\n      \n        var views: [String : Any] = [\"titleLabel\": titleLabel!, \"stepper\": stepper!, \"valueLabel\": valueLabel!]\n        let metrics = [\"spacing\": 15.0]\n        valueLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)\n        titleLabel.setContentCompressionResistancePriority(.defaultHigh, for: .horizontal)\n      \n        let title = shouldShowTitle ? \"[titleLabel]-(>=15@250)-\" : \"\"\n      \n        if let imageView = imageView, let _ = imageView.image {\n            views[\"imageView\"] = imageView\n            let hContraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[imageView]-(15)-\\(title)[valueLabel]-[stepper]-|\", options: .alignAllCenterY, metrics: metrics, views: views)\n            imageView.translatesAutoresizingMaskIntoConstraints = false\n            dynamicConstraints.append(contentsOf: hContraints)\n        } else {\n            let hContraints = NSLayoutConstraint.constraints(withVisualFormat: \"H:|-\\(title)[valueLabel]-[stepper]-|\", options: .alignAllCenterY, metrics: metrics, views: views)\n            dynamicConstraints.append(contentsOf: hContraints)\n        }\n        let vContraint = NSLayoutConstraint(item: stepper!, attribute: .centerY, relatedBy: .equal, toItem: contentView, attribute: .centerY, multiplier: 1, constant: 0)\n        dynamicConstraints.append(vContraint)\n        contentView.addConstraints(dynamicConstraints)\n    }\n  \n}\n\n// MARK: StepperRow\n\nopen class _StepperRow: Row<StepperCell> {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = { value in\n                                guard let value = value else { return nil }\n                                return DecimalFormatter().string(from: NSNumber(value: value)) }\n    }\n}\n\n/// Double row that has a UIStepper as accessoryType\npublic final class StepperRow: _StepperRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/SwitchRow.swift",
    "content": "//  SwitchRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// MARK: SwitchCell\n\nopen class SwitchCell: Cell<Bool>, CellType {\n\n    @IBOutlet public weak var switchControl: UISwitch!\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n        let switchC = UISwitch()\n        switchControl = switchC\n        accessoryView = switchControl\n        editingAccessoryView = accessoryView\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func setup() {\n        super.setup()\n        selectionStyle = .none\n        switchControl.addTarget(self, action: #selector(SwitchCell.valueChanged), for: .valueChanged)\n    }\n\n    deinit {\n        switchControl?.removeTarget(self, action: nil, for: .allEvents)\n    }\n\n    open override func update() {\n        super.update()\n        switchControl.isOn = row.value ?? false\n        switchControl.isEnabled = !row.isDisabled\n    }\n\n    @objc (switchValueDidChange) func valueChanged() {\n        row.value = switchControl?.isOn ?? false\n    }\n}\n\n// MARK: SwitchRow\n\nopen class _SwitchRow: Row<SwitchCell> {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        displayValueFor = nil\n    }\n}\n\n/// Boolean row that has a UISwitch as accessoryType\npublic final class SwitchRow: _SwitchRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/TextAreaRow.swift",
    "content": "//  TextAreaRow.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\n// TODO: Temporary workaround for Xcode 10 beta\n#if swift(>=4.2)\nimport UIKit.UIGeometry\nextension UIEdgeInsets {\n    static let zero = UIEdgeInsets()\n}\n#endif\n\npublic enum TextAreaHeight {\n    case fixed(cellHeight: CGFloat)\n    case dynamic(initialTextViewHeight: CGFloat)\n}\n\npublic enum TextAreaMode {\n    case normal\n    case readOnly\n}\n\nprotocol TextAreaConformance: FormatterConformance {\n    var placeholder: String? { get set }\n    var textAreaHeight: TextAreaHeight { get set }\n    var titlePercentage: CGFloat? { get set}\n}\n\n/**\n *  Protocol for cells that contain a UITextView\n */\npublic protocol AreaCell: TextInputCell {\n    var textView: UITextView! { get }\n}\n\nextension AreaCell {\n    public var textInput: UITextInput {\n        return textView\n    }\n}\n\nopen class _TextAreaCell<T> : Cell<T>, UITextViewDelegate, AreaCell where T: Equatable, T: InputTypeInitiable {\n\n    @IBOutlet public weak var textView: UITextView!\n    @IBOutlet public weak var placeholderLabel: UILabel?\n\n    private var awakeFromNibCalled = false\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n\n        let textView: UITextView\n        if #available(iOS 16, *) {\n            textView = UITextView(usingTextLayoutManager: false)\n        } else {\n            textView = UITextView()\n        }\n        self.textView = textView\n        textView.translatesAutoresizingMaskIntoConstraints = false\n        textView.keyboardType = .default\n        textView.font = .preferredFont(forTextStyle: .body)\n        textView.textContainer.lineFragmentPadding = 0\n        textView.textContainerInset = UIEdgeInsets.zero\n        textView.backgroundColor = .clear\n        contentView.addSubview(textView)\n\n        let placeholderLabel = UILabel()\n        self.placeholderLabel = placeholderLabel\n        placeholderLabel.translatesAutoresizingMaskIntoConstraints = false\n        placeholderLabel.numberOfLines = 0\n        if #available(iOS 13.0, *) {\n            placeholderLabel.textColor = UIColor.tertiaryLabel\n        } else {\n            placeholderLabel.textColor = UIColor(white: 0, alpha: 0.22)\n        }\n        placeholderLabel.font = textView.font\n        contentView.addSubview(placeholderLabel)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func awakeFromNib() {\n        super.awakeFromNib()\n        awakeFromNibCalled = true\n    }\n\n    open var dynamicConstraints = [NSLayoutConstraint]()\n\n    open override func setup() {\n        super.setup()\n        let textAreaRow = row as! TextAreaConformance\n        switch textAreaRow.textAreaHeight {\n        case .dynamic(_):\n            height = { UITableView.automaticDimension }\n            textView.isScrollEnabled = false\n        case .fixed(let cellHeight):\n            height = { cellHeight }\n        }\n\n        textView.delegate = self\n        selectionStyle = .none\n        if !awakeFromNibCalled {\n            imageView?.addObserver(self, forKeyPath: \"image\", options: [.new, .old], context: nil)\n        }\n        setNeedsUpdateConstraints()\n    }\n\n    deinit {\n        textView?.delegate = nil\n        if !awakeFromNibCalled {\n            imageView?.removeObserver(self, forKeyPath: \"image\")\n        }\n    }\n\n    open override func update() {\n        super.update()\n        textLabel?.text = nil\n        detailTextLabel?.text = nil\n        textView.isEditable = !row.isDisabled\n        if #available(iOS 13.0, *) {\n            textView.textColor = row.isDisabled ? .tertiaryLabel : .label\n        } else {\n            textView.textColor = row.isDisabled ? .gray : .black\n        }\n        textView.text = row.displayValueFor?(row.value)\n        placeholderLabel?.text = (row as? TextAreaConformance)?.placeholder\n        placeholderLabel?.isHidden = textView.text.count != 0\n    }\n\n    open override func cellCanBecomeFirstResponder() -> Bool {\n        return !row.isDisabled && textView?.canBecomeFirstResponder == true\n    }\n\n    open override func cellBecomeFirstResponder(withDirection: Direction) -> Bool {\n        // workaround to solve https://github.com/xmartlabs/Eureka/issues/887 UIKit issue\n        textView?.perform(#selector(UITextView.becomeFirstResponder), with: nil, afterDelay: 0.0)\n        return true\n\n    }\n\n    open override func cellResignFirstResponder() -> Bool {\n        return textView?.resignFirstResponder() ?? true\n    }\n\n    open override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {\n        let obj = object as AnyObject?\n\n        if let keyPathValue = keyPath, let changeType = change?[NSKeyValueChangeKey.kindKey], obj === imageView && keyPathValue == \"image\" &&\n            (changeType as? NSNumber)?.uintValue == NSKeyValueChange.setting.rawValue, !awakeFromNibCalled {\n            setNeedsUpdateConstraints()\n            updateConstraintsIfNeeded()\n        }\n    }\n\n    //Mark: Helpers\n\n    private func displayValue(useFormatter: Bool) -> String? {\n        guard let v = row.value else { return nil }\n        if let formatter = (row as? FormatterConformance)?.formatter, useFormatter {\n            return textView?.isFirstResponder == true ? formatter.editingString(for: v) : formatter.string(for: v)\n        }\n        return String(describing: v)\n    }\n\n    // MARK: TextFieldDelegate\n\n    open func textViewDidBeginEditing(_ textView: UITextView) {\n        formViewController()?.beginEditing(of: self)\n        formViewController()?.textInputDidBeginEditing(textView, cell: self)\n        if let textAreaConformance = (row as? TextAreaConformance), let _ = textAreaConformance.formatter, textAreaConformance.useFormatterOnDidBeginEditing ?? textAreaConformance.useFormatterDuringInput {\n            textView.text = self.displayValue(useFormatter: true)\n        } else {\n            textView.text = self.displayValue(useFormatter: false)\n        }\n    }\n\n    open func textViewDidEndEditing(_ textView: UITextView) {\n        formViewController()?.endEditing(of: self)\n        formViewController()?.textInputDidEndEditing(textView, cell: self)\n        textViewDidChange(textView)\n        textView.text = displayValue(useFormatter: (row as? FormatterConformance)?.formatter != nil)\n    }\n\n    open func textViewDidChange(_ textView: UITextView) {\n\n        if let textAreaConformance = row as? TextAreaConformance, case .dynamic = textAreaConformance.textAreaHeight, let tableView = formViewController()?.tableView {\n            let currentOffset = tableView.contentOffset\n            UIView.performWithoutAnimation {\n                tableView.beginUpdates()\n                tableView.endUpdates()\n            }\n            tableView.setContentOffset(currentOffset, animated: false)\n        }\n        placeholderLabel?.isHidden = textView.text.count != 0\n        guard let textValue = textView.text else {\n            row.value = nil\n            return\n        }\n        guard let formatterRow = row as? FormatterConformance, let formatter = formatterRow.formatter else {\n            row.value = textValue.isEmpty ? nil : (T.init(string: textValue) ?? row.value)\n            return\n        }\n        if formatterRow.useFormatterDuringInput {\n            let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))\n            let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n            if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                row.value = value.pointee as? T\n                guard var selStartPos = textView.selectedTextRange?.start else { return }\n                let oldVal = textView.text\n                textView.text = row.displayValueFor?(row.value)\n                selStartPos = (formatter as? FormatterProtocol)?.getNewPosition(forPosition: selStartPos, inTextInput: textView, oldValue: oldVal, newValue: textView.text) ?? selStartPos\n                textView.selectedTextRange = textView.textRange(from: selStartPos, to: selStartPos)\n                return\n            }\n        } else {\n            let value: AutoreleasingUnsafeMutablePointer<AnyObject?> = AutoreleasingUnsafeMutablePointer<AnyObject?>.init(UnsafeMutablePointer<T>.allocate(capacity: 1))\n            let errorDesc: AutoreleasingUnsafeMutablePointer<NSString?>? = nil\n            if formatter.getObjectValue(value, for: textValue, errorDescription: errorDesc) {\n                row.value = value.pointee as? T\n            }\n        }\n    }\n\n    open func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {\n        return formViewController()?.textInput(textView, shouldChangeCharactersInRange: range, replacementString: text, cell: self) ?? true\n    }\n\n    open func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {\n        if let textAreaRow = self.row as? _TextAreaRow, textAreaRow.textAreaMode == .readOnly {\n            return false\n        }\n        return formViewController()?.textInputShouldBeginEditing(textView, cell: self) ?? true\n    }\n\n    open func textViewShouldEndEditing(_ textView: UITextView) -> Bool {\n        return formViewController()?.textInputShouldEndEditing(textView, cell: self) ?? true\n    }\n\n    open override func updateConstraints() {\n        customConstraints()\n        super.updateConstraints()\n    }\n\n    open func customConstraints() {\n        guard !awakeFromNibCalled else { return }\n\n        contentView.removeConstraints(dynamicConstraints)\n        dynamicConstraints = []\n        var views: [String: AnyObject] = [\"textView\": textView, \"label\": placeholderLabel!]\n        dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[label]\", options: [], metrics: nil, views: views))\n        if let textAreaConformance = row as? TextAreaConformance, case .dynamic(let initialTextViewHeight) = textAreaConformance.textAreaHeight {\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[textView(>=initialHeight@800)]-|\", options: [], metrics: [\"initialHeight\": initialTextViewHeight], views: views))\n        } else {\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"V:|-[textView]-|\", options: [], metrics: nil, views: views))\n        }\n        if let imageView = imageView, let _ = imageView.image {\n            views[\"imageView\"] = imageView\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[textView]-|\", options: [], metrics: nil, views: views))\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"H:[imageView]-(15)-[label]-|\", options: [], metrics: nil, views: views))\n        } else if let titlePercentage = (row as? TextAreaConformance)?.titlePercentage, titlePercentage > 0.0 {\n            textView.textAlignment = .right\n            dynamicConstraints += NSLayoutConstraint.constraints(withVisualFormat: \"H:[textView]-|\", options: [], metrics: nil, views: views)\n            let sideSpaces = (layoutMargins.right + layoutMargins.left)\n            dynamicConstraints.append(NSLayoutConstraint(item: textView!,\n                                                         attribute: .width,\n                                                         relatedBy: .equal,\n                                                         toItem: contentView,\n                                                         attribute: .width,\n                                                         multiplier: 1 - titlePercentage,\n                                                         constant: -sideSpaces))\n        } else {\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[textView]-|\", options: [], metrics: nil, views: views))\n            dynamicConstraints.append(contentsOf: NSLayoutConstraint.constraints(withVisualFormat: \"H:|-[label]-|\", options: [], metrics: nil, views: views))\n        }\n        contentView.addConstraints(dynamicConstraints)\n    }\n\n}\n\nopen class TextAreaCell: _TextAreaCell<String>, CellType {\n\n    required public init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n}\n\nopen class AreaRow<Cell: CellType>: FormatteableRow<Cell>, TextAreaConformance where Cell: BaseCell, Cell: AreaCell {\n\n    open var placeholder: String?\n    open var textAreaHeight = TextAreaHeight.fixed(cellHeight: 110)\n    open var textAreaMode = TextAreaMode.normal\n    /// The percentage of the cell that should be occupied by the remaining space to the left of the textArea. This is equivalent to the space occupied by a title in FieldRow, making the textArea aligned to fieldRows using the same titlePercentage. This behavior works only if the cell does not contain an image, due to its automatically set constraints in the cell.\n    open var titlePercentage: CGFloat?\n\n    public required init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\nopen class _TextAreaRow: AreaRow<TextAreaCell> {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n\n/// A row with a UITextView where the user can enter large text.\npublic final class TextAreaRow: _TextAreaRow, RowType {\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n}\n"
  },
  {
    "path": "Source/Rows/TriplePickerInputRow.swift",
    "content": "//\n//  TriplePickerInputRow.swift\n//  Eureka\n//\n//  Created by Mathias Claassen on 5/10/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Foundation\nimport UIKit\n\nopen class TriplePickerInputCell<A, B, C> : _PickerInputCell<Tuple3<A, B, C>> where A: Equatable, B: Equatable, C: Equatable {\n\n    private var pickerRow: _TriplePickerInputRow<A, B, C>! { return row as? _TriplePickerInputRow<A, B, C> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        if let selectedValue = pickerRow.value, let indexA = pickerRow.firstOptions().firstIndex(of: selectedValue.a),\n            let indexB = pickerRow.secondOptions(selectedValue.a).firstIndex(of: selectedValue.b),\n            let indexC = pickerRow.thirdOptions(selectedValue.a, selectedValue.b).firstIndex(of: selectedValue.c){\n            picker.selectRow(indexA, inComponent: 0, animated: true)\n            picker.selectRow(indexB, inComponent: 1, animated: true)\n            picker.selectRow(indexC, inComponent: 2, animated: true)\n        }\n    }\n\n    open override func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 3\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        if component == 0 {\n            return pickerRow.firstOptions().count\n        } else if component == 1 {\n            return pickerRow.secondOptions(pickerRow.selectedFirst()).count\n        } else {\n            return pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond()).count\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        if component == 0 {\n            return pickerRow.displayValueForFirstRow(pickerRow.firstOptions()[row])\n        } else if component == 1 {\n            return pickerRow.displayValueForSecondRow(pickerRow.secondOptions(pickerRow.selectedFirst())[row])\n        } else {\n            return pickerRow.displayValueForThirdRow(pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond())[row])\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {\n        if component == 0 {\n            let a = pickerRow.firstOptions()[row]\n            if let value = pickerRow.value {\n                guard value.a != a else {\n                    return\n                }\n\n                let b: B = pickerRow.secondOptions(a).contains(value.b) ? value.b : pickerRow.secondOptions(a)[0]\n                let c: C = pickerRow.thirdOptions(a, b).contains(value.c) ? value.c : pickerRow.thirdOptions(a, b)[0]\n                pickerRow.value = Tuple3(a: a, b: b, c: c)\n                pickerView.reloadComponent(1)\n                pickerView.reloadComponent(2)\n                if b != value.b {\n                    pickerView.selectRow(0, inComponent: 1, animated: true)\n                }\n                if c != value.c {\n                    pickerView.selectRow(0, inComponent: 2, animated: true)\n                }\n            } else {\n                let b = pickerRow.secondOptions(a)[0]\n                pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n                pickerView.reloadComponent(1)\n                pickerView.reloadComponent(2)\n                pickerView.selectRow(0, inComponent: 1, animated: true)\n                pickerView.selectRow(0, inComponent: 2, animated: true)\n            }\n        } else if component == 1 {\n            let a = pickerRow.selectedFirst()\n            let b = pickerRow.secondOptions(a)[row]\n            if let value = pickerRow.value {\n                guard value.b != b else {\n                    return\n                }\n                if pickerRow.thirdOptions(a, b).contains(value.c) {\n                    pickerRow.value = Tuple3(a: a, b: b, c: value.c)\n                    pickerView.reloadComponent(2)\n                    update()\n                    return\n                } else {\n                    pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n                }\n            } else {\n                pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n            }\n            pickerView.reloadComponent(2)\n            pickerView.selectRow(0, inComponent: 2, animated: true)\n        } else {\n            let a = pickerRow.selectedFirst()\n            let b = pickerRow.selectedSecond()\n            pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[row])\n        }\n        update()\n    }\n}\n\nopen class _TriplePickerInputRow<A: Equatable, B: Equatable, C: Equatable> : Row<TriplePickerInputCell<A, B, C>>, NoValueDisplayTextConformance {\n\n    open var noValueDisplayText: String? = nil\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = {_ in []}\n    /// Options for third component given the selected value from the first and second components. Will be called often so should be O(1)\n    public var thirdOptions: ((A, B) -> [C]) = {_, _ in []}\n    \n    /// Modify the displayed values for the first picker row.\n    public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }\n    /// Modify the displayed values for the second picker row.\n    public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }\n    /// Modify the displayed values for the third picker row.\n    public var displayValueForThirdRow: ((C) -> (String)) = { c in return String(describing: c) }\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    func selectedFirst() -> A {\n        return value?.a ?? firstOptions()[0]\n    }\n\n    func selectedSecond() -> B {\n        return value?.b ?? secondOptions(selectedFirst())[0]\n    }\n\n}\n\n/// A generic row where the user can pick an option from a picker view displayed in the keyboard area\npublic final class TriplePickerInputRow<A, B, C>: _TriplePickerInputRow<A, B, C>, RowType where A: Equatable, B: Equatable, C: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n        self.displayValueFor = { [weak self] tuple in\n            guard let tuple = tuple else {\n                return self?.noValueDisplayText\n            }\n            return String(describing: tuple.a) + \", \" + String(describing: tuple.b) + \", \" + String(describing: tuple.c)\n        }\n    }\n}\n"
  },
  {
    "path": "Source/Rows/TriplePickerRow.swift",
    "content": "//\n//  TriplePickerRow.swift\n//  Eureka\n//\n//  Created by Mathias Claassen on 5/9/18.\n//  Copyright © 2018 Xmartlabs. All rights reserved.\n//\n\nimport Foundation\nimport UIKit\n\npublic struct Tuple3<A: Equatable, B: Equatable, C: Equatable> {\n    public let a: A\n    public let b: B\n    public let c: C\n\n    public init(a: A, b: B, c: C) {\n        self.a = a\n        self.b = b\n        self.c = c\n    }\n\n}\n\nextension Tuple3: Equatable {}\n\npublic func == <A: Equatable, B: Equatable, C: Equatable>(lhs: Tuple3<A, B, C>, rhs: Tuple3<A, B, C>) -> Bool {\n    return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.c\n}\n\n// MARK: MultiplePickerCell\n\nopen class TriplePickerCell<A, B, C> : _PickerCell<Tuple3<A, B, C>> where A: Equatable, B: Equatable, C: Equatable {\n\n    private var pickerRow: _TriplePickerRow<A, B, C>? { return row as? _TriplePickerRow<A, B, C> }\n\n    public required init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {\n        super.init(style: style, reuseIdentifier: reuseIdentifier)\n    }\n\n    required public init?(coder aDecoder: NSCoder) {\n        super.init(coder: aDecoder)\n    }\n\n    open override func update() {\n        super.update()\n        if let selectedValue = pickerRow?.value, let indexA = pickerRow?.firstOptions().firstIndex(of: selectedValue.a),\n            let indexB = pickerRow?.secondOptions(selectedValue.a).firstIndex(of: selectedValue.b),\n            let indexC = pickerRow?.thirdOptions(selectedValue.a, selectedValue.b).firstIndex(of: selectedValue.c) {\n            picker.selectRow(indexA, inComponent: 0, animated: true)\n            picker.selectRow(indexB, inComponent: 1, animated: true)\n            picker.selectRow(indexC, inComponent: 2, animated: true)\n        }\n    }\n\n    open override func numberOfComponents(in pickerView: UIPickerView) -> Int {\n        return 3\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {\n        guard let pickerRow = pickerRow else { return 0 }\n        if component == 0 {\n            return pickerRow.firstOptions().count\n        } else if component == 1 {\n            return pickerRow.secondOptions(pickerRow.selectedFirst()).count\n        } else {\n            return pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond()).count\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {\n        guard let pickerRow = pickerRow else { return \"\" }\n        if component == 0 {\n            return pickerRow.displayValueForFirstRow(pickerRow.firstOptions()[row])\n        } else if component == 1 {\n            return pickerRow.displayValueForSecondRow(pickerRow.secondOptions(pickerRow.selectedFirst())[row])\n        } else {\n            return pickerRow.displayValueForThirdRow(pickerRow.thirdOptions(pickerRow.selectedFirst(), pickerRow.selectedSecond())[row])\n        }\n    }\n\n    open override func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {\n        guard let pickerRow = pickerRow else { return }\n        if component == 0 {\n            let a = pickerRow.firstOptions()[row]\n            if let value = pickerRow.value {\n                guard value.a != a else {\n                    return\n                }\n\n                let b: B = pickerRow.secondOptions(a).contains(value.b) ? value.b : pickerRow.secondOptions(a)[0]\n                let c: C = pickerRow.thirdOptions(a, b).contains(value.c) ? value.c : pickerRow.thirdOptions(a, b)[0]\n                pickerRow.value = Tuple3(a: a, b: b, c: c)\n                pickerView.reloadComponent(1)\n                pickerView.reloadComponent(2)\n                if b != value.b {\n                    pickerView.selectRow(0, inComponent: 1, animated: true)\n                }\n                if c != value.c {\n                    pickerView.selectRow(0, inComponent: 2, animated: true)\n                }\n            } else {\n                let b = pickerRow.secondOptions(a)[0]\n                pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n                pickerView.reloadComponent(1)\n                pickerView.reloadComponent(2)\n                pickerView.selectRow(0, inComponent: 1, animated: true)\n                pickerView.selectRow(0, inComponent: 2, animated: true)\n            }\n        } else if component == 1 {\n            let a = pickerRow.selectedFirst()\n            let b = pickerRow.secondOptions(a)[row]\n            if let value = pickerRow.value {\n                guard value.b != b else {\n                    return\n                }\n                if pickerRow.thirdOptions(a, b).contains(value.c) {\n                    pickerRow.value = Tuple3(a: a, b: b, c: value.c)\n                    pickerView.reloadComponent(2)\n                    return\n                } else {\n                    pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n                }\n            } else {\n                pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[0])\n            }\n            pickerView.reloadComponent(2)\n            pickerView.selectRow(0, inComponent: 2, animated: true)\n        } else {\n            let a = pickerRow.selectedFirst()\n            let b = pickerRow.selectedSecond()\n            pickerRow.value = Tuple3(a: a, b: b, c: pickerRow.thirdOptions(a, b)[row])\n        }\n    }\n\n}\n\n// MARK: PickerRow\nopen class _TriplePickerRow<A, B, C> : Row<TriplePickerCell<A, B, C>> where A: Equatable, B: Equatable, C: Equatable {\n\n    /// Options for first component. Will be called often so should be O(1)\n    public var firstOptions: (() -> [A]) = {[]}\n    /// Options for second component given the selected value from the first component. Will be called often so should be O(1)\n    public var secondOptions: ((A) -> [B]) = {_ in []}\n    /// Options for third component given the selected value from the first and second components. Will be called often so should be O(1)\n    public var thirdOptions: ((A, B) -> [C]) = {_, _ in []}\n    \n    /// Modify the displayed values for the first picker row.\n    public var displayValueForFirstRow: ((A) -> (String)) = { a in return String(describing: a) }\n    /// Modify the displayed values for the second picker row.\n    public var displayValueForSecondRow: ((B) -> (String)) = { b in return String(describing: b) }\n    /// Modify the displayed values for the third picker row.\n    public var displayValueForThirdRow: ((C) -> (String)) = { c in return String(describing: c) }\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n    func selectedFirst() -> A {\n        return value?.a ?? firstOptions()[0]\n    }\n\n    func selectedSecond() -> B {\n        return value?.b ?? secondOptions(selectedFirst())[0]\n    }\n\n}\n\n/// A generic row where the user can pick an option from a picker view\npublic final class TriplePickerRow<A, B, C>: _TriplePickerRow<A, B, C>, RowType where A: Equatable, B: Equatable, C: Equatable {\n\n    required public init(tag: String?) {\n        super.init(tag: tag)\n    }\n\n}\n"
  },
  {
    "path": "Source/Validations/RuleClosure.swift",
    "content": "//  RuleClosure.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct RuleClosure<T: Equatable>: RuleType {\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public var closure: (T?) -> ValidationError?\n\n    public func isValid(value: T?) -> ValidationError? {\n        return closure(value)\n    }\n\n    public init(validationError: ValidationError = ValidationError(msg: \"Field validation fails..\"), id: String? = nil, closure: @escaping ((T?) -> ValidationError?)) {\n        self.validationError = validationError\n        self.closure = closure\n        self.id = id\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleEmail.swift",
    "content": "//  RuleEmail.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic class RuleEmail: RuleRegExp {\n\n    public init(msg: String = \"Field value should be a valid email!\", id: String? = nil) {\n        super.init(regExpr: RegExprPattern.EmailAddress.rawValue, allowsEmpty: true, msg: msg, id: id)\n    }\n\n}\n"
  },
  {
    "path": "Source/Validations/RuleEqualsToRow.swift",
    "content": "//  RuleRequire.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct RuleEqualsToRow<T: Equatable>: RuleType {\n\n    public init(form: Form, tag: String, msg: String = \"Fields don't match!\", id: String? = nil) {\n        self.validationError = ValidationError(msg: msg)\n        self.form = form\n        self.tag = tag\n        self.row = nil\n        self.id = id\n    }\n\n    public init(row: RowOf<T>, msg: String = \"Fields don't match!\", id: String? = nil) {\n        self.validationError = ValidationError(msg: msg)\n        self.form = nil\n        self.tag = nil\n        self.row = row\n        self.id = id\n    }\n\n    public var id: String?\n    public var validationError: ValidationError\n    public weak var form: Form?\n    public var tag: String?\n    public weak var row: RowOf<T>?\n\n    public func isValid(value: T?) -> ValidationError? {\n        let rowAux: RowOf<T> = row ?? form!.rowBy(tag: tag!)!\n        return rowAux.value == value ? nil : validationError\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleLength.swift",
    "content": "//  RuleLength.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct RuleMinLength: RuleType {\n\n    let min: UInt\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(minLength: UInt, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must have at least \\(minLength) characters\"\n        min = minLength\n        validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: String?) -> ValidationError? {\n        guard let value = value, !value.isEmpty else { return nil }\n        return value.count < Int(min) ? validationError : nil\n    }\n}\n\npublic struct RuleMaxLength: RuleType {\n\n    let max: UInt\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(maxLength: UInt, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must have less than \\(maxLength) characters\"\n        max = maxLength\n        validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: String?) -> ValidationError? {\n        guard let value = value, !value.isEmpty else { return nil }\n        return value.count > Int(max) ? validationError : nil\n    }\n}\n\npublic struct RuleExactLength: RuleType {\n    let length: UInt\n    \n    public var id: String?\n    public var validationError: ValidationError\n    \n    public init(exactLength: UInt, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must have exactly \\(exactLength) characters\"\n        length = exactLength\n        validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n    \n    public func isValid(value: String?) -> ValidationError? {\n        guard let value = value, !value.isEmpty else { return nil }\n        return value.count != Int(length) ? validationError : nil\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleRange.swift",
    "content": "//  RuleRange.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct RuleGreaterThan<T: Comparable>: RuleType {\n\n    let min: T\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(min: T, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must be greater than \\(min)\"\n        self.min = min\n        self.validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: T?) -> ValidationError? {\n        guard let val = value else { return nil }\n        guard val > min else { return validationError }\n        return nil\n    }\n}\n\npublic struct RuleGreaterOrEqualThan<T: Comparable>: RuleType {\n\n    let min: T\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(min: T, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must be greater or equals than \\(min)\"\n        self.min = min\n        self.validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: T?) -> ValidationError? {\n        guard let val = value else { return nil }\n        guard val >= min else { return validationError }\n        return nil\n    }\n}\n\npublic struct RuleSmallerThan<T: Comparable>: RuleType {\n\n    let max: T\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(max: T, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ??  \"Field value must be smaller than \\(max)\"\n        self.max = max\n        self.validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: T?) -> ValidationError? {\n        guard let val = value else { return nil }\n        guard val < max else { return validationError }\n        return nil\n    }\n}\n\npublic struct RuleSmallerOrEqualThan<T: Comparable>: RuleType {\n\n    let max: T\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public init(max: T, msg: String? = nil, id: String? = nil) {\n        let ruleMsg = msg ?? \"Field value must be smaller or equals than \\(max)\"\n        self.max = max\n        self.validationError = ValidationError(msg: ruleMsg)\n        self.id = id\n    }\n\n    public func isValid(value: T?) -> ValidationError? {\n        guard let val = value else { return nil }\n        guard val <= max else { return validationError }\n        return nil\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleRegExp.swift",
    "content": "//  RegexRule.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic enum RegExprPattern: String {\n    case EmailAddress = \"^[_A-Za-z0-9-+!?#$%'`*/=~^{}|]+(\\\\.[_A-Za-z0-9-+!?#$%'`*/=~^{}|]+)*@[A-Za-z0-9-]+(\\\\.[A-Za-z0-9-]+)*(\\\\.[A-Za-z‌​]{2,})$\"\n    case URL = \"^(?:(?:http|https)://)(?:\\\\S+(?::\\\\S*)?@)?(?:(?:(?:[1-9]\\\\d?|1\\\\d\\\\d|2[01]\\\\d|22[0-3])(?:\\\\.(?:1?\\\\d{1,2}|2[0-4]\\\\d|25[0-5])){2}(?:\\\\.(?:[0-9]\\\\d?|1\\\\d\\\\d|2[0-4]\\\\d|25[0-4]))|(?:(?:[a-z\\\\u00a1-\\\\uffff0-9]+-?)*[a-z\\\\u00a1-\\\\uffff0-9]+)(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff0-9]+-?)*[a-z\\\\u00a1-\\\\uffff0-9]+)*(?:\\\\.(?:[a-z\\\\u00a1-\\\\uffff]{2,})))|localhost)(?::\\\\d{2,5})?(?:(/|\\\\?|#)[^\\\\s]*)?$\"\n    case ContainsNumber = \".*\\\\d.*\"\n    case ContainsCapital = \"^.*?[A-Z].*?$\"\n    case ContainsLowercase = \"^.*?[a-z].*?$\"\n}\n\nopen class RuleRegExp: RuleType {\n\n    public var regExpr: String = \"\"\n    public var id: String?\n    public var validationError: ValidationError\n    public var allowsEmpty = true\n\n    public init(regExpr: String, allowsEmpty: Bool = true, msg: String = \"Invalid field value!\", id: String? = nil) {\n        self.validationError = ValidationError(msg: msg)\n        self.regExpr = regExpr\n        self.allowsEmpty = allowsEmpty\n        self.id = id\n    }\n\n    public func isValid(value: String?) -> ValidationError? {\n        if let value = value, !value.isEmpty {\n            let predicate = NSPredicate(format: \"SELF MATCHES %@\", regExpr)\n            guard predicate.evaluate(with: value) else {\n                return validationError\n            }\n            return nil\n        } else if !allowsEmpty {\n            return validationError\n        }\n        return nil\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleRequired.swift",
    "content": "//  RuleRequire.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\n\npublic struct RuleRequired<T: Equatable>: RuleType {\n\n    public init(msg: String = \"Field required!\", id: String? = nil) {\n        self.validationError = ValidationError(msg: msg)\n        self.id = id\n    }\n\n    public var id: String?\n    public var validationError: ValidationError\n\n    public func isValid(value: T?) -> ValidationError? {\n        if let str = value as? String {\n            return str.isEmpty ? validationError : nil\n        }\n        return value != nil ? nil : validationError\n    }\n}\n"
  },
  {
    "path": "Source/Validations/RuleURL.swift",
    "content": "//  RuleURL.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport Foundation\nimport UIKit\n\npublic struct RuleURL: RuleType {\n\n    public init(allowsEmpty: Bool = true, requiresProtocol: Bool = false, msg: String = \"Field value must be an URL!\", id: String? = nil) {\n        validationError = ValidationError(msg: msg)\n        self.allowsEmpty = allowsEmpty\n        self.requiresProtocol = requiresProtocol\n        self.id = id\n    }\n\n    public var id: String?\n    public var allowsEmpty = true\n    public var requiresProtocol = false\n    public var validationError: ValidationError\n\n    public func isValid(value: URL?) -> ValidationError? {\n        if let value = value, value.absoluteString.isEmpty == false {\n            let predicate = NSPredicate(format:\"SELF MATCHES %@\", RegExprPattern.URL.rawValue)\n            guard predicate.evaluate(with: value.absoluteString) else {\n                return validationError\n            }\n            return nil\n        } else if !allowsEmpty {\n            return validationError\n        }\n        return nil\n    }\n}\n"
  },
  {
    "path": "Tests/BaseEurekaTests.swift",
    "content": "//  BaseEurekaTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass BaseEurekaTests: XCTestCase {\n    var dateForm = Form()\n    var fieldForm = Form()\n    var shortForm = Form()\n    var manySectionsForm = Form()\n    var formVC = FormViewController()\n\n    override func setUp() {\n        super.setUp()\n\n        // load the view to test the cells\n        formVC.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        formVC.tableView?.frame = formVC.view.frame\n\n        // Create a Date section containing one date row of each type and some extra rows that use minimumDate, maximumDate and minuteInterval restrictions\n        dateForm +++ Section(\"Date Section\")\n            <<< DateRow(\"DateRow_d1\") { $0.title = \"Date\"; $0.value = Date() }\n            <<< DateTimeRow(\"DateTimeRow_d1\") { $0.title = \"DateTime\"; $0.value = Date() }\n            <<< TimeRow(\"TimeRow_d1\") { $0.title = \"Time\"; $0.value = Date() }\n            <<< CountDownRow(\"CountDownRow_d1\") { $0.title = \"CountDown\"; $0.value = Date() }\n            <<< DateRow(\"MinDateRow_d1\") { $0.title = \"Date(min)\"; $0.value = Date(); $0.minimumDate = $0.value?.addingTimeInterval(-60*60*24) }\n            <<< DateRow(\"MaxDateRow_d1\") { $0.title = \"Date(max)\"; $0.value = Date(); $0.maximumDate = $0.value?.addingTimeInterval(60*60*24) }\n            <<< DateRow(\"MinMaxDateRow_d1\") { $0.title = \"Date(min/max)\"; $0.value = Date(); $0.minimumDate = $0.value?.addingTimeInterval(-60*60*24); $0.maximumDate = $0.value?.addingTimeInterval(60*60*24)  }\n            <<< DateRow(\"IntervalDateRow_d1\") { $0.title = \"Date(interval)\"; $0.value = Date(); $0.minuteInterval = 15 }\n\n        shortForm +++ Section(\"short\")\n            <<< NameRow(\"NameRow_s1\") { $0.title = \"Name\" }\n            <<< IntRow(\"IntRow_s1\") { $0.title = \"Age\" }\n\n        fieldForm +++ Section(\"Field Section\")\n            <<< TextRow(\"TextRow_f1\") { $0.title = \"Text\" }\n            <<< NameRow(\"NameRow_f1\") { $0.title = \"Name\" }\n            <<< EmailRow(\"EmailRow_f1\") { $0.title = \"Email\" }\n            <<< PhoneRow(\"PhoneRow_f1\") { $0.title = \"Phone\" }\n            <<< PasswordRow(\"PasswordRow_f1\") { $0.title = \"Password\" }\n            <<< URLRow(\"UrlRow_f1\") { $0.title = \"Url\" }\n            <<< IntRow(\"IntRow_f1\") { $0.title = \"Int\" }\n            <<< DecimalRow(\"DecimalRow_f1\") { $0.title = \"Decimal\" }\n            <<< TwitterRow(\"TwitterRow_f1\") { $0.title = \"Twitter\" }\n            <<< AccountRow(\"AccountRow_f1\") { $0.title = \"Account\" }\n            <<< ZipCodeRow(\"ZipCodeRow_f1\") { $0.title = \"Zip Code\" }\n\n        manySectionsForm =  Section(\"Section A\")\n                        +++ Section(\"Section B\")\n                        +++ Section(\"Section C\")\n                        +++ Section(\"Section D\")\n                        +++ Section(\"Section E\")\n                        +++ Section(\"Section F\")\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n        dateForm = Form()\n        shortForm = Form()\n        fieldForm = Form()\n        manySectionsForm = Form()\n        formVC = FormViewController()\n    }\n\n    func testTearUp() {\n        XCTAssertEqual(dateForm.count, 1)\n        XCTAssertEqual(dateForm[0].count, 8)\n        XCTAssertEqual(shortForm[0].count, 2)\n        XCTAssertEqual(fieldForm.count, 1)\n        XCTAssertEqual(fieldForm[0].count, 11)\n        XCTAssertEqual(manySectionsForm.count, 6)\n        XCTAssertEqual(manySectionsForm[0].count, 0)\n    }\n}\n\npublic class MyFormDelegate: FormDelegate {\n    public var valuesChanged = 0\n    public var rowsAdded = 0\n    public var sectionsAdded = 0\n    public var rowsRemoved = 0\n    public var sectionsRemoved = 0\n    public var rowsReplacedIn = 0\n    public var sectionsReplacedIn = 0\n    public var rowsReplacedOut = 0\n    public var sectionsReplacedOut = 0\n\n    public func valueHasBeenChanged(for: BaseRow, oldValue: Any?, newValue: Any?) {\n        valuesChanged += 1\n    }\n\n    public func sectionsHaveBeenAdded(_ sections: [Section], at: IndexSet) {\n        sectionsAdded += sections.count\n    }\n\n    public func sectionsHaveBeenRemoved(_ sections: [Section], at: IndexSet) {\n        sectionsRemoved += sections.count\n    }\n\n    public func sectionsHaveBeenReplaced(oldSections: [Section], newSections: [Section], at: IndexSet) {\n        sectionsReplacedIn += newSections.count\n        sectionsReplacedOut += oldSections.count\n    }\n\n    public func rowsHaveBeenAdded(_ rows: [BaseRow], at: [IndexPath]) {\n        rowsAdded += rows.count\n    }\n\n    public func rowsHaveBeenRemoved(_ rows: [BaseRow], at: [IndexPath]) {\n        rowsRemoved += rows.count\n    }\n\n    public func rowsHaveBeenReplaced(oldRows: [BaseRow], newRows: [BaseRow], at: [IndexPath]) {\n        rowsReplacedIn += newRows.count\n        rowsReplacedOut += oldRows.count\n    }\n\n}\n"
  },
  {
    "path": "Tests/CallbacksTests.swift",
    "content": "//  CallbacksTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass CallbacksTests: XCTestCase {\n\n    var formVC = FormViewController()\n\n    override func setUp() {\n        super.setUp()\n        // load the view to test the cells\n        formVC.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        formVC.tableView?.frame = formVC.view.frame\n    }\n\n    override func tearDown() {\n        super.tearDown()\n    }\n\n    func testOnChange() {\n        onChangeTest(row:TextRow(), value: \"text\")\n        onChangeTest(row:IntRow(), value: 33)\n        onChangeTest(row:DecimalRow(), value: 35.7)\n        onChangeTest(row:URLRow(), value: URL(string: \"http://xmartlabs.com\")!)\n        onChangeTest(row:DateRow(), value: Date().addingTimeInterval(100))\n        onChangeTest(row:DateInlineRow(), value: Date().addingTimeInterval(100))\n        onChangeTest(row:PopoverSelectorRow<String>(), value: \"text\")\n        onChangeTest(row:SliderRow(), value: 5.0)\n        onChangeTest(row:StepperRow(), value: 2.5)\n        onChangeTest(row:PickerInputRow(), value: \"Option 2\")\n    }\n\n    func testCellSetup() {\n        cellSetupTest(row:TextRow())\n        cellSetupTest(row:IntRow())\n        cellSetupTest(row:DecimalRow())\n        cellSetupTest(row:URLRow())\n        cellSetupTest(row:DateRow())\n        cellSetupTest(row:DateInlineRow())\n        cellSetupTest(row:PopoverSelectorRow<String>())\n        cellSetupTest(row:SliderRow())\n        cellSetupTest(row:StepperRow())\n        cellSetupTest(row:PickerInputRow<String>())\n    }\n\n    func testCellUpdate() {\n        cellUpdateTest(row:TextRow())\n        cellUpdateTest(row:IntRow())\n        cellUpdateTest(row:DecimalRow())\n        cellUpdateTest(row:URLRow())\n        cellUpdateTest(row:DateRow())\n        cellUpdateTest(row:DateInlineRow())\n        cellUpdateTest(row:PopoverSelectorRow<String>())\n        cellUpdateTest(row:SliderRow())\n        cellUpdateTest(row:StepperRow())\n        cellUpdateTest(row:PickerInputRow<String>())\n    }\n\n    func testDefaultCellSetup() {\n        defaultCellSetupTest(row:TextRow())\n        defaultCellSetupTest(row:IntRow())\n        defaultCellSetupTest(row:DecimalRow())\n        defaultCellSetupTest(row:URLRow())\n        defaultCellSetupTest(row:DateRow())\n        defaultCellSetupTest(row:DateInlineRow())\n        defaultCellSetupTest(row:PopoverSelectorRow<String>())\n        defaultCellSetupTest(row:SliderRow())\n        defaultCellSetupTest(row:StepperRow())\n        defaultCellSetupTest(row:PickerInputRow<String>())\n    }\n\n    func testDefaultCellUpdate() {\n       defaultCellUpdateTest(row: TextRow())\n       defaultCellUpdateTest(row: IntRow())\n       defaultCellUpdateTest(row: DecimalRow())\n       defaultCellUpdateTest(row: URLRow())\n       defaultCellUpdateTest(row: DateRow())\n       defaultCellUpdateTest(row: DateInlineRow())\n       defaultCellUpdateTest(row: PopoverSelectorRow<String>())\n       defaultCellUpdateTest(row: SliderRow())\n       defaultCellUpdateTest(row: StepperRow())\n       defaultCellUpdateTest(row: PickerInputRow<String>())\n    }\n\n    func testDefaultInitializers() {\n       defaultInitializerTest(row: TextRow())\n       defaultInitializerTest(row: IntRow())\n       defaultInitializerTest(row: DecimalRow())\n       defaultInitializerTest(row: URLRow())\n       defaultInitializerTest(row: DateRow())\n       defaultInitializerTest(row: DateInlineRow())\n       defaultInitializerTest(row: PopoverSelectorRow<String>())\n       defaultInitializerTest(row: SliderRow())\n       defaultInitializerTest(row: StepperRow())\n       defaultInitializerTest(row: PickerInputRow<String>())\n    }\n\n    func testOnRowValidationChenged() {\n        onRowValidationTests(row: TextRow(), value: \"Eureka!\")\n        onRowValidationTests(row: IntRow(), value: 33)\n        onRowValidationTests(row: DecimalRow(), value: 35.7)\n        onRowValidationTests(row: URLRow(), value: URL(string: \"http://xmartlabs.com\")!)\n        onRowValidationTests(row: DateRow(), value: Date().addingTimeInterval(100))\n        onRowValidationTests(row: DateInlineRow(), value: Date().addingTimeInterval(100))\n        onRowValidationTests(row: PopoverSelectorRow<String>(), value: \"text\")\n        onRowValidationTests(row: SliderRow(), value: 5.0)\n        onRowValidationTests(row: StepperRow(), value: 2.5)\n        onRowValidationTests(row: TimeInlineRow(), value: Date())\n        onRowValidationTests(row: PickerInputRow<String>(), value: \"Hi!!\")\n    }\n\n    private func onChangeTest<Row, Value>(row:Row, value:Value) where Row: BaseRow, Row: RowType, Value == Row.Cell.Value {\n        var invoked = false\n        row.onChange { _ in\n            invoked = true\n        }\n        formVC.form +++ Section() <<< row\n        row.value = value\n        XCTAssertTrue(invoked)\n    }\n\n    private func cellSetupTest<Row, Value>(row:Row) where  Row: BaseRow, Row : RowType, Value == Row.Cell.Value {\n        var invoked = false\n        row.cellSetup { _, _ in\n            invoked = true\n        }\n        formVC.form +++ Section() <<< row\n        let _ = row.cell // laod cell\n        XCTAssertTrue(invoked)\n    }\n\n    private func cellUpdateTest<Row, Value>(row:Row) where  Row: BaseRow, Row : RowType, Value == Row.Cell.Value {\n        var invoked = false\n        row.cellUpdate { _, _ in\n            invoked = true\n        }\n        formVC.form +++ Section() <<< row\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: row.indexPath!) // should invoke cell update\n        XCTAssertTrue(invoked)\n    }\n\n    func onRowValidationTests<Row, Value>(row:Row, value:Value) where Row: BaseRow, Row: RowType, Value == Row.Cell.Value {\n        var invoked = false\n        row.validationOptions = ValidationOptions.validatesOnChange\n        row.add(rule: RuleClosure { _ in return ValidationError(msg: \"Validation Error\") })\n        row.onRowValidationChanged { _, _ in\n            invoked = true\n        }\n        formVC.form +++ Section() <<< row\n        row.value = value\n\n        XCTAssertTrue(invoked)\n    }\n\n    private func defaultInitializerTest<Row>(row:Row) where Row: BaseRow, Row : RowType {\n        var invoked = false\n        Row.defaultRowInitializer = { row in\n            invoked = true\n        }\n        formVC.form +++ Row.init { _ in }\n        XCTAssertTrue(invoked)\n    }\n\n    private func defaultCellSetupTest<Row>(row:Row) where Row: BaseRow, Row: RowType {\n        var invoked = false\n        Row.defaultCellSetup = { cell, row in\n            invoked = true\n        }\n        formVC.form +++ row\n        let _ = row.cell // laod cell\n        XCTAssertTrue(invoked)\n    }\n\n    private func defaultCellUpdateTest<Row>(row:Row) where Row: BaseRow, Row : RowType {\n        var invoked = false\n        Row.defaultCellUpdate = { cell, row in\n            invoked = true\n        }\n        formVC.form +++ row\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: row.indexPath!) // should invoke cell update\n        XCTAssertTrue(invoked)\n    }\n}\n"
  },
  {
    "path": "Tests/CollectionTests.swift",
    "content": "//  CollectionTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass CollectionTests: BaseEurekaTests {\n\n    func testSectionRangeReplaceableCollectionTypeConformance() {\n        // test if the collection function work as expected\n\n        fieldForm[0].replaceSubrange(Range(3...6), with: [CheckRow(\"check1_ctx\")])          // replacing 4 rows with 1\n        XCTAssertEqual(fieldForm[0].count, 8)                                                       // fieldform had 10 rows prior to replacing\n        fieldForm[0][4] = CheckRow(\"check2_ctx\")                                                    // replacing 5th row\n        XCTAssertEqual(fieldForm[0].count, 8)\n        let rows: [BaseRow] = fieldForm[0].filter({ $0 is CheckRow })\n        XCTAssertEqual(rows.count, 2)                            // Do I have 2 CheckRows??\n\n        fieldForm[0].append(contentsOf: [CheckRow(\"check3_ctx\"), CheckRow(\"check4_ctx\"), CheckRow(\"check5_ctx\")])\n        // is the same as fieldForm[0] += [...]\n\n        XCTAssertEqual(fieldForm[0].count, 11)\n    }\n\n    func testFormRangeReplaceableCollectionTypeConformance() {\n        // test if the collection function work as expected\n\n        manySectionsForm.replaceSubrange(2..<5, with: [Section(\"Out of order\"), Section()])         // replacing 3 rows with 2\n        XCTAssertEqual(manySectionsForm.count, 5)                                                                  // fieldform had 10 rows prior to replacing\n        manySectionsForm[3] = Section(\"There is no order anyway\")                                               // replacing 4th row\n        XCTAssertEqual(manySectionsForm.count, 5)\n        let sections: [Section] = manySectionsForm.filter({ $0.header?.title?.contains(\"order\") ?? false})\n        \n        XCTAssertEqual(sections.count, 2)\n\n        manySectionsForm.append(contentsOf: [Section(\"1\"), Section(\"2\")])\n        // is the same as fieldForm[0] += [...]\n\n        XCTAssertEqual(manySectionsForm.count, 7)\n    }\n\n    func testDelegateFunctions() {\n        // Test operators\n        let form = Form()\n        let delegate = MyFormDelegate()\n        form.delegate = delegate\n\n        form +++ Section(\"A\")                                                                  // addsection + 1\n        form +++ TextRow(\"textrow1_ctx\") { $0.value = \" \"}                                      // addsection + 1\n        form +++ Section(\"C\") <<< TextRow(\"textrow2_ctx\") <<< TextRow(\"textrow3_ctx\")          // addsection + 1\n\n        XCTAssertEqual(delegate.sectionsAdded, 3)\n        XCTAssertEqual(delegate.rowsAdded, 0)\n\n        form[0][0] = TextRow(\"textrow6_ctx\")                                                    // addrow + 1\n        form[1][0].baseValue = \"a\"                                                              // valueschanged + 1\n\n        XCTAssertEqual(delegate.valuesChanged, 1)\n        XCTAssertEqual(delegate.sectionsAdded, 3)\n        XCTAssertEqual(delegate.rowsAdded, 1)\n\n        form[2][1] = TextRow(\"textrow7_ctx\")                                                    // replacerowIn+1, replacerowOut+1,\n        form.replaceSubrange(Range(0...1), with: [Section(\"replaced in\")])              // replacesectionOut+1, sectionremoved+1, replacesectionin+1\n\n        XCTAssertEqual(delegate.sectionsRemoved, 1)\n\n        form[1].removeAll()                                                                     // rowsremoved + 2\n        form.removeAll()                                                                        // sectionsremoved + 2\n\n        //Test delegate\n        XCTAssertEqual(delegate.valuesChanged, 1)\n        XCTAssertEqual(delegate.sectionsAdded, 3)\n        XCTAssertEqual(delegate.rowsAdded, 1)\n        XCTAssertEqual(delegate.sectionsRemoved, 3)\n        XCTAssertEqual(delegate.rowsRemoved, 2)\n        XCTAssertEqual(delegate.rowsReplacedIn, 1)\n        XCTAssertEqual(delegate.rowsReplacedOut, 1)\n        XCTAssertEqual(delegate.sectionsReplacedIn, 1)\n        XCTAssertEqual(delegate.sectionsReplacedOut, 1)\n    }\n\n}\n"
  },
  {
    "path": "Tests/DateTests.swift",
    "content": "//  DateTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass DateTests: BaseEurekaTests {\n\n    override func setUp() {\n        super.setUp()\n        formVC.form = dateForm\n    }\n\n    func testMinMax() {\n\n        let minRow: DateRow! = formVC.form.rowBy(tag: \"MinDateRow_d1\")\n        let maxRow: DateRow!  = formVC.form.rowBy(tag: \"MaxDateRow_d1\")\n        let minMaxRow: DateRow! = formVC.form.rowBy(tag: \"MinMaxDateRow_d1\")\n\n        XCTAssertNotNil(minRow.indexPath)\n        XCTAssertNotNil(maxRow.indexPath)\n        XCTAssertNotNil(minMaxRow.indexPath)\n\n        // make sure cellSetup is called for each cell\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: minRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: maxRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: minMaxRow.indexPath!)\n\n        //make sure cell update is called for each cell\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: minRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: maxRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: minMaxRow.indexPath!)\n\n        XCTAssertNil(minRow.cell.datePicker.maximumDate)\n        XCTAssertEqual(minRow.cell.datePicker.minimumDate, minRow.value?.addingTimeInterval(-60*60*24))\n        XCTAssertNil(maxRow.cell.datePicker.minimumDate)\n        XCTAssertEqual(maxRow.cell.datePicker.maximumDate, maxRow.value?.addingTimeInterval(60*60*24))\n\n        XCTAssertNotNil(minMaxRow.cell.datePicker.minimumDate)\n        XCTAssertEqual(minMaxRow.cell.datePicker.maximumDate, minMaxRow.cell.datePicker.minimumDate!.addingTimeInterval(2*60*60*24))\n    }\n\n    func testInterval() {\n        let row: DateRow? = formVC.form.rowBy(tag: \"IntervalDateRow_d1\")\n\n        XCTAssertNotNil(row?.indexPath)\n\n        // make sure cellSetup is called for each cell\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: row!.indexPath!)\n\n        //make sure cell update is called for each cell\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: row!.indexPath!)\n\n        XCTAssertEqual(row?.cell.datePicker.minuteInterval, 15)\n\n    }\n\n}\n"
  },
  {
    "path": "Tests/FormValuesTests.swift",
    "content": "//  FormValuesTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass FormValuesTests: BaseEurekaTests {\n\n    override func setUp() {\n        super.setUp()\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n\n    func testFormValues() {\n        let form = Form()\n\n        let textRow = TextRow(\"RowTag\")\n\n        form +++ Section() <<< textRow\n\n        // check that the row is included in the values dictionary\n        XCTAssertEqual(form.values(includeHidden: true).count, 1)\n        // check that the row value is nil\n        XCTAssertTrue(form.values(includeHidden: true)[\"RowTag\"]! == nil)\n\n        // change the value and check that the new value appears\n        textRow.value = \"Hi!\"\n        XCTAssertTrue(form.values(includeHidden: true)[\"RowTag\"] is String)\n        XCTAssertEqual(form.values(includeHidden: true)[\"RowTag\"] as? String, \"Hi!\")\n\n        let textRowWithoutTag = TextRow()\n        form +++ Section() <<< textRowWithoutTag\n\n        XCTAssertEqual(form.values(includeHidden: true).count, 1)\n        XCTAssertTrue(form.values(includeHidden: true)[\"RowTag\"] is String)\n\n        let textRowInvisible = TextRow(\"InvisibleRowTag\")\n        textRowInvisible.hidden = true\n        form +++ Section() <<< textRowInvisible\n\n        XCTAssertEqual(form.values(includeHidden: true).count, 2)\n        XCTAssertTrue(form.values(includeHidden: true)[\"RowTag\"] is String)\n\n        XCTAssertEqual(form.allRows.count, 3)\n        XCTAssertEqual(form.rows.count, 2)\n        XCTAssertEqual(form.values().count, 1)\n        XCTAssertEqual(form.values(includeHidden: true).count, 2)\n    }\n\n    func testIncludeHiddenFormValues() {\n        let form = Form()\n\n        let textRow = TextRow(\"RowTag\")\n\n        form +++ Section() <<< textRow\n\n        // check that the row is included in the values dictionary\n        XCTAssertEqual(form.values().count, 1)\n        // check that the row value is nil\n        XCTAssertTrue(form.values()[\"RowTag\"]! == nil)\n\n        // change the value and check that the new value appears\n        textRow.value = \"Hi!\"\n        XCTAssertTrue(form.values()[\"RowTag\"] is String)\n        XCTAssertEqual(form.values()[\"RowTag\"] as? String, \"Hi!\")\n\n        let textRowWithoutTag = TextRow()\n        form +++ Section() <<< textRowWithoutTag\n\n        XCTAssertEqual(form.values().count, 1)\n        XCTAssertTrue(form.values()[\"RowTag\"] is String)\n\n        let textRowInvisible = TextRow(\"InvisibleRowTag\")\n        textRowInvisible.hidden = true\n        textRowInvisible.value = \"Bye!\"\n        form +++ Section() <<< textRowInvisible\n\n        XCTAssertEqual(form.values(includeHidden: true).count, 2)\n        XCTAssertTrue(form.values(includeHidden: true)[\"RowTag\"] is String)\n        XCTAssertTrue(form.values(includeHidden: true)[\"InvisibleRowTag\"] is String)\n\n        XCTAssertEqual(form.allRows.count, 3)\n        XCTAssertEqual(form.rows.count, 2)\n        XCTAssertEqual(form.values().count, 1)\n        XCTAssertEqual(form.values(includeHidden: true).count, 2)\n    }\n\n}\n"
  },
  {
    "path": "Tests/HelperMethodTests.swift",
    "content": "//  HelperMethodTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass HelperMethodTests: BaseEurekaTests {\n\n    func testRowByTag() {\n        // Tests rowBy(tag: ) method\n\n        let urlRow: URLRow? = fieldForm.rowBy(tag: \"UrlRow_f1\")\n        XCTAssertNotNil(urlRow)\n\n        let phoneRow: PhoneRow? = fieldForm.rowBy(tag: \"phone\")\n        XCTAssertNil(phoneRow)\n    }\n\n    func testRowSequenceMethods() {\n        // Tests the nextRowForRow() and the previousRowForRow() methods\n\n        let form = fieldForm + shortForm + dateForm\n        let row6 = form.nextRow(for: form[0][5])\n\n        XCTAssertEqual(row6, form[0][6])\n        XCTAssertEqual(row6, form.rowBy(tag: \"IntRow_f1\") as? IntRow)\n\n        let row_5_and_6: ArraySlice<BaseRow> = form[0][5...6]\n        XCTAssertEqual(row_5_and_6[5], form[0][5])\n        XCTAssertEqual(row_5_and_6[6], form[0][6])\n\n        let row10n = form.nextRow(for: form[0][8])\n        let rownil = form.nextRow(for: form[2][7])\n\n        XCTAssertEqual(row10n, form[0][9])\n        XCTAssertNil(rownil)\n\n        let row10p = form.previousRow(for: form[0][10])\n        let rowNilP = form.previousRow(for: form[0][0])\n\n        XCTAssertEqual(row10n, row10p)\n        XCTAssertNil(rowNilP)\n\n        XCTAssertNotNil(form.nextRow(for: form[1][1]))\n        XCTAssertEqual(form[1][1], form.previousRow(for: form.nextRow(for: form[1][1])!))\n    }\n\n    func testAllRowsMethod() {\n        // Tests the allRows() method\n\n        let form = fieldForm + shortForm + dateForm\n        XCTAssertEqual(form.rows.count, 21)\n        XCTAssertEqual(form.rows[12], shortForm[0][1])\n        XCTAssertEqual(form.rows[20], form.rowBy(tag: \"IntervalDateRow_d1\") as? DateRow)\n    }\n\n    func testAllRowsWrappedByTagMethod() {\n        // Tests the allRows() method\n\n        let form = fieldForm + shortForm + dateForm\n\n        let rows = form.dictionaryValuesToEvaluatePredicate()\n\n        XCTAssertEqual(rows.count, 21)\n    }\n\n    func testDisabledRows() {\n        // Tests that a row set up as disabled can not become firstResponder\n\n        let checkRow = CheckRow(\"check\") { $0.disabled = true }\n        let switchRow = SwitchRow(\"switch\") { $0.disabled = true }\n        let segmentedRow = SegmentedRow<String>(\"segments\") { $0.disabled = true; $0.options = [\"a\", \"b\"] }\n        let intRow = IntRow(\"int\") { $0.disabled = true }\n\n        formVC.form +++ checkRow <<< switchRow <<< segmentedRow <<< intRow\n\n        checkRow.updateCell()\n        XCTAssertTrue(checkRow.cell.selectionStyle == .none)\n\n        switchRow.updateCell()\n        XCTAssertNotNil(switchRow.cell.switchControl)\n        XCTAssertFalse(switchRow.cell.switchControl!.isEnabled)\n\n        segmentedRow.updateCell()\n        XCTAssertFalse(segmentedRow.cell.segmentedControl.isEnabled)\n\n        intRow.updateCell()\n        XCTAssertFalse(intRow.cell.cellCanBecomeFirstResponder())\n\n    }\n\n    func testAllSectionsMethod() {\n        let form = manySectionsForm\n\n        let sections = form\n        let allSections = form.allSections\n\n        XCTAssertEqual(sections.count, 6)\n        XCTAssertEqual(sections.count, allSections.count)\n\n        let section1 = form[0]\n        let section4 = form[3]\n        form.hideSection(section1)\n        form.hideSection(section4)\n\n        XCTAssertEqual(sections.count, 4)\n        XCTAssertEqual(allSections.count, 6)\n    }\n\n}\n"
  },
  {
    "path": "Tests/HiddenRowsTests.swift",
    "content": "//  HiddenRowsTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass HiddenRowsTests: BaseEurekaTests {\n    var form: Form!\n    let row10 = IntRow(\"int1_hrt\") {\n        $0.hidden = \"$IntRow_s1 > 23\"\n    }\n    let row11 = TextRow(\"txt1_hrt\") {\n        $0.hidden = .function([\"NameRow_s1\"], { form in\n                        if let r1: NameRow = form.rowBy(tag: \"NameRow_s1\") {\n                            return r1.value?.contains(\" is \") ?? false\n                        }\n                        return false\n                    })\n    }\n\n    let sec2 = Section(\"Whatsoever\") {\n        $0.tag = \"s3_hrt\"\n        $0.hidden = \"$NameRow_s1 contains 'God'\"\n    }\n    let row20 = TextRow(\"txt2_hrt\") {\n        $0.hidden = .function([\"IntRow_s1\", \"NameRow_s1\"], { form in\n                        if let r1: IntRow = form.rowBy(tag: \"IntRow_s1\"), let r2: NameRow = form.rowBy(tag: \"NameRow_s1\") {\n                            return r1.value == 88 || r2.value?.hasSuffix(\"real\") ?? false\n                        }\n                        return false\n                    })\n    }\n    let inlineDateRow21 = DateInlineRow {\n        $0.hidden = \"$IntRow_s1 > 23\"\n    }\n\n    override func setUp() {\n        super.setUp()\n        form = shortForm\n            +++ row10\n            <<< row11\n            +++ sec2\n            <<< row20\n            <<< inlineDateRow21\n    }\n\n    func testAddRowToObserver() {\n\n        let intDep = form.rowObservers[\"IntRow_s1\"]?[.hidden]\n        let nameDep = form.rowObservers[\"NameRow_s1\"]?[.hidden]\n\n        // make sure we can unwrap\n        XCTAssertNotNil(intDep)\n        XCTAssertNotNil(nameDep)\n\n        // test rowObservers\n        XCTAssertEqual(intDep!.count, 3)\n        XCTAssertEqual(nameDep!.count, 3)\n\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"txt2_hrt\" }))\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n        XCTAssertFalse(intDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag ==  \"txt2_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"txt1_hrt\" }))\n        XCTAssertFalse(nameDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n\n        //This should not change when some rows hide ...\n        form[0][0].baseValue = \"God is real\"\n        form[0][1].baseValue = 88\n\n        //check everything is still the same\n        XCTAssertEqual(intDep!.count, 3)\n        XCTAssertEqual(nameDep!.count, 3)\n\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"txt2_hrt\" }))\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n        XCTAssertFalse(intDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"txt2_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"txt1_hrt\" }))\n        XCTAssertFalse(nameDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n\n        // ...nor if they reappear\n        form[0][0].baseValue = \"blah blah blah\"\n        form[0][1].baseValue = 1\n\n        //check everything is still the same\n        XCTAssertEqual(intDep!.count, 3)\n        XCTAssertEqual(nameDep!.count, 3)\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"txt2_hrt\" }))\n        XCTAssertTrue(intDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n        XCTAssertFalse(intDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"txt2_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"s3_hrt\" }))\n        XCTAssertTrue(nameDep!.contains(where: { $0.tag == \"txt1_hrt\" }))\n        XCTAssertFalse(nameDep!.contains(where: { $0.tag == \"int1_hrt\" }))\n\n        // Test a condition with nil\n        let newRow = TextRow(\"new_row\") {\n            $0.hidden = \"$txt1_hrt == nil\"\n        }\n\n        form.last! <<< newRow\n        XCTAssertTrue(newRow.hiddenCache)\n    }\n\n    func testItemsByTag() {\n        // test that all rows and sections with tag are there\n        XCTAssertEqual(form.rowBy(tag: \"NameRow_s1\"), form[0][0])\n        XCTAssertEqual(form.rowBy(tag: \"IntRow_s1\"), form[0][1])\n\n        XCTAssertEqual(form.rowBy(tag: \"int1_hrt\"), row10)\n        XCTAssertEqual(form.rowBy(tag: \"txt1_hrt\"), row11)\n\n        XCTAssertEqual(form.sectionBy(tag: \"s3_hrt\"), sec2)\n        XCTAssertEqual(form.rowBy(tag: \"txt2_hrt\"), row20)\n\n        // check that these are all in there\n        XCTAssertEqual(form.rowsByTag.count, 5)\n\n        // what happens after hiding the rows? Let's cause havoc\n        form[0][0].baseValue = \"God is real\"\n        form[0][1].baseValue = 88\n\n        // we still want the same results here\n        XCTAssertEqual(form.rowBy(tag: \"NameRow_s1\"), form[0][0])\n        XCTAssertEqual(form.rowBy(tag: \"IntRow_s1\"), form[0][1])\n        XCTAssertEqual(form.rowBy(tag: \"int1_hrt\"), row10)\n        XCTAssertEqual(form.rowBy(tag: \"txt1_hrt\"), row11)\n        XCTAssertEqual(form.sectionBy(tag: \"s3_hrt\"), sec2)\n        XCTAssertEqual(form.rowBy(tag: \"txt2_hrt\"), row20)\n        XCTAssertEqual(form.rowsByTag.count, 5)\n\n        // and let them come up again\n        form[0][0].baseValue = \"blah blah\"\n        form[0][1].baseValue = 1\n\n        // we still want the same results here\n        XCTAssertEqual(form.rowsByTag[\"NameRow_s1\"], form[0][0])\n        XCTAssertEqual(form.rowsByTag[\"IntRow_s1\"], form[0][1])\n        XCTAssertEqual(form.rowsByTag[\"int1_hrt\"], row10)\n        XCTAssertEqual(form.rowsByTag[\"txt1_hrt\"], row11)\n        XCTAssertEqual(form.sectionBy(tag: \"s3_hrt\"), sec2)\n        XCTAssertEqual(form.rowsByTag[\"txt2_hrt\"], row20)\n        XCTAssertEqual(form.rowsByTag.count, 5)\n    }\n\n    func testCorrectValues() {\n\n        //initial empty values (none is hidden)\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(sec2.count, 2)\n\n        // false values\n        form[0][0].baseValue = \"Hi there\"\n        form[0][1].baseValue = 15\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(sec2.count, 2)\n\n        // hide 'int1_hrt' row\n        form[0][1].baseValue = 24\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 1)\n        XCTAssertEqual(sec2.count, 1)\n        XCTAssertEqual(form[1][0].tag, \"txt1_hrt\")\n\n        // hide 'txt1_hrt' and 'txt2_hrt'\n        form[0][0].baseValue = \" is real\"\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 0)\n        XCTAssertEqual(sec2.count, 0)\n\n        // let the last section disappear\n        form[0][0].baseValue = \"God is real\"\n\n        XCTAssertEqual(form.count, 2)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 0)\n\n        // and see if they come back to live\n        form[0][0].baseValue = \"blah\"\n        form[0][1].baseValue = 2\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(sec2.count, 2)\n    }\n\n    func testInlineRows() {\n        //initial empty values (none is hidden)\n        XCTAssertEqual(sec2.count, 2)\n\n        // change dependency value\n        form[0][1].baseValue = 25\n\n        XCTAssertEqual(sec2.count, 1)\n\n        // change dependency value\n        form[0][1].baseValue = 10\n        XCTAssertEqual(sec2.count, 2)\n\n        //hide inline row when expanded\n        inlineDateRow21.expandInlineRow()\n\n        // check that the row is expanded\n        XCTAssertEqual(sec2.count, 3)\n\n        // hide expanded inline row\n        form[0][1].baseValue = 25\n        XCTAssertEqual(sec2.count, 1)\n\n        // make inline row visible again\n        form[0][1].baseValue = 10\n        XCTAssertEqual(sec2.count, 2)\n    }\n\n    func testHiddenSections() {\n        let s1 = Section {\n            $0.hidden = \"$NameRow_s1 contains 'hello'\"\n            $0.tag = \"s1_ths\"\n        }\n        let s2 = Section {\n            $0.hidden = \"$NameRow_s1 contains 'morning'\"\n            $0.tag = \"s2_ths\"\n        }\n        form.insert(s1, at: 1)\n        form.insert(s2, at: 3)\n\n        /* what we should have here\n        \n        shortForm (1 section)\n        s1\n        { row10, row11 }\n        s2\n        sec2 (2 rows)\n        */\n\n        XCTAssertEqual(form.count, 5)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 0)\n        XCTAssertEqual(form[2].count, 2)\n        XCTAssertEqual(form[3].count, 0)\n        XCTAssertEqual(form[4].count, 2)\n\n        form[0][0].baseValue = \"hello, good morning!\"\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(form[2].count, 2)\n\n        form[0][0].baseValue = \"whatever\"\n\n        XCTAssertEqual(form.count, 5)\n        XCTAssertEqual(form[1].tag, \"s1_ths\")\n        XCTAssertEqual(form[3].tag, \"s2_ths\")\n        XCTAssertEqual(form[4].tag, \"s3_hrt\")\n    }\n\n    func testInsertionIndex() {\n        let r1 = CheckRow(\"check1_tii_hrt\") { $0.hidden = \"$NameRow_s1 contains 'morning'\" }\n        let r2 = CheckRow(\"check2_tii_hrt\") { $0.hidden = \"$NameRow_s1 contains 'morning'\" }\n        let r3 = CheckRow(\"check3_tii_hrt\") { $0.hidden = \"$NameRow_s1 contains 'good'\" }\n        let r4 = CheckRow(\"check4_tii_hrt\") { $0.hidden = \"$NameRow_s1 contains 'good'\" }\n\n        form[0].insert(r1, at: 1)\n        form[1].insert(contentsOf: [r2, r3], at: 0)\n\n        //test correct insert\n\n        XCTAssertEqual(form[0].count, 3)\n        XCTAssertEqual(form[0][1].tag, \"check1_tii_hrt\")\n\n        XCTAssertEqual(form[1].count, 4)\n        XCTAssertEqual(form[1][0].tag, \"check2_tii_hrt\")\n        XCTAssertEqual(form[1][1].tag, \"check3_tii_hrt\")\n\n        // hide these rows\n        form[0][0].baseValue = \"hello, good morning!\"\n\n        // insert another row\n        form[1].insert(r4, at: 1)\n\n        XCTAssertEqual(form[1].count, 2) // all inserted rows should be hidden\n        XCTAssertEqual(form[1][0].tag, \"int1_hrt\")\n        XCTAssertEqual(form[1][1].tag, \"txt1_hrt\")\n\n        form[0][0].baseValue = \"whatever\"\n\n        // we inserted r4 at index 1 but there were two rows hidden before it as well so it shall be at index 3\n        XCTAssertEqual(form[1].count, 5)\n        XCTAssertEqual(form[1][0].tag, \"check2_tii_hrt\")\n        XCTAssertEqual(form[1][1].tag, \"check3_tii_hrt\")\n        XCTAssertEqual(form[1][2].tag, \"int1_hrt\")\n        XCTAssertEqual(form[1][3].tag, \"check4_tii_hrt\")\n        XCTAssertEqual(form[1][4].tag, \"txt1_hrt\")\n\n        form[0][0].baseValue = \"hello, good morning!\"\n\n        //check that hidden rows get removed as well\n        form[1].removeAll()\n\n        //inserting 2 rows at the end, deleting 1\n        form[2].replaceSubrange(1..<2, with: [r2, r4])\n\n        XCTAssertEqual(form[1].count, 0)\n        XCTAssertEqual(form[2].count, 1)\n        XCTAssertEqual(form[2][0].tag, \"txt2_hrt\")\n\n        form[0][0].baseValue = \"whatever\"\n\n        XCTAssertEqual(form[2].count, 3)\n        XCTAssertEqual(form[2][0].tag, \"txt2_hrt\")\n        XCTAssertEqual(form[2][1].tag, \"check2_tii_hrt\")\n        XCTAssertEqual(form[2][2].tag, \"check4_tii_hrt\")\n\n    }\n}\n"
  },
  {
    "path": "Tests/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>$(PRODUCT_NAME)</string>\n\t<key>CFBundlePackageType</key>\n\t<string>BNDL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>4.3.1</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>1</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "Tests/MultivaluedSectionTests.swift",
    "content": "//  MultivaluedSectionTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2017 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass MultivaluedSectionTests: XCTestCase {\n\n    var formVC = FormViewController()\n\n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n\n        formVC = FormViewController()\n        formVC.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        formVC.tableView?.frame = formVC.view.frame\n\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n\n    func testHeaders() {\n        let headerSection = MultivaluedSection(multivaluedOptions: .Insert, header: \"Header Text\", footer: nil) { _ in }\n        XCTAssertEqual(headerSection.header!.title, \"Header Text\")\n        XCTAssertNil(headerSection.footer)\n    }\n\n    func testFooters() {\n        let footerSection = MultivaluedSection(multivaluedOptions: .Insert, header: nil, footer: \"Footer Text\") { _ in }\n        XCTAssertEqual(footerSection.footer!.title, \"Footer Text\")\n        XCTAssertNil(footerSection.header)\n    }\n\n    func testAddButton() {\n        let section = MultivaluedSection(multivaluedOptions: .Insert, header: \"\", footer: \"\") { _ in\n            // just an empty closure\n        }\n        XCTAssertEqual(section.count, 1)\n\n        let section2 = MultivaluedSection(multivaluedOptions: .Reorder, header: \"\", footer: \"\") { _ in\n            // just an empty closure\n        }\n        XCTAssertEqual(section2.count, 0)\n    }\n\n    func testDelegateMethods() {\n        let form = Form()\n        let section = MultivaluedSection(multivaluedOptions: .Insert, header: \"\", footer: \"\") { section in\n            section.tag = \"textrows\"\n            section <<< TextRow() {\n                $0.value = \"text\"\n            }\n        }\n\n        form +++ section\n        formVC.form = form\n\n        // values\n        XCTAssertEqual(form.values().keys.count, 1)\n        XCTAssertEqual(form.values()[\"textrows\"] as! [String], [\"text\"])\n\n        // canEditRowAt\n        XCTAssertTrue(formVC.tableView(formVC.tableView, canEditRowAt: IndexPath(item: 0, section: 0)))\n        form +++ Section() <<< TextRow()\n        XCTAssertFalse(formVC.tableView(formVC.tableView, canEditRowAt: IndexPath(item: 0, section: 1)))\n\n        // editingStyleForRowAt\n        XCTAssertEqual(formVC.tableView(formVC.tableView, editingStyleForRowAt: IndexPath(item: 1, section: 0)), UITableViewCell.EditingStyle.insert)\n        XCTAssertEqual(formVC.tableView(formVC.tableView, editingStyleForRowAt: IndexPath(item: 0, section: 0)), UITableViewCell.EditingStyle.none)\n        XCTAssertEqual(formVC.tableView(formVC.tableView, editingStyleForRowAt: IndexPath(item: 0, section: 1)), UITableViewCell.EditingStyle.none)\n\n        form +++ MultivaluedSection(multivaluedOptions: .Delete, header: \"\", footer: \"\") { _ in } <<< TextRow()\n\n        XCTAssertEqual(formVC.tableView(formVC.tableView, editingStyleForRowAt: IndexPath(item: 0, section: 2)), UITableViewCell.EditingStyle.delete)\n\n        // shouldIndentWhileEditingRowAt\n        XCTAssertFalse(formVC.tableView(formVC.tableView, shouldIndentWhileEditingRowAt: IndexPath(item: 0, section: 0)))\n        XCTAssertTrue(formVC.tableView(formVC.tableView, shouldIndentWhileEditingRowAt: IndexPath(item: 1, section: 0)))\n\n        XCTAssertFalse(formVC.tableView(formVC.tableView, shouldIndentWhileEditingRowAt: IndexPath(item: 0, section: 1)))\n        XCTAssertTrue(formVC.tableView(formVC.tableView, shouldIndentWhileEditingRowAt: IndexPath(item: 0, section: 2)))\n\n        // canMoveRowAt\n        XCTAssertFalse(formVC.tableView(formVC.tableView, canMoveRowAt:  IndexPath(item: 0, section: 0)))\n        XCTAssertFalse(formVC.tableView(formVC.tableView, canMoveRowAt:  IndexPath(item: 1, section: 0)))\n\n        form +++ MultivaluedSection(multivaluedOptions: .Reorder, header: \"\", footer: \"\") { _ in } <<< TextRow()\n        XCTAssertFalse(formVC.tableView(formVC.tableView, canMoveRowAt:  IndexPath(item: 0, section: 3)))\n\n        form.last! <<< TextRow()\n\n        XCTAssertTrue(formVC.tableView(formVC.tableView, canMoveRowAt:  IndexPath(item: 0, section: 3)))\n        XCTAssertTrue(formVC.tableView(formVC.tableView, canMoveRowAt:  IndexPath(item: 1, section: 3)))\n\n    }\n}\n"
  },
  {
    "path": "Tests/OperatorsTest.swift",
    "content": "//  OperatorsTest.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass OperatorsTest: BaseEurekaTests {\n\n    func testOperators() {\n        // test the operators\n\n        var form = Form()\n        form +++ TextRow(\"textrow1_ctx\")\n            <<< TextRow(\"textrow2_ctx\")\n        form = form + (TextRow(\"textrow3_ctx\")\n            <<< TextRow(\"textrow4_ctx\")\n            +++ TextRow(\"textrow5_ctx\")\n            <<< TextRow(\"textrow6_ctx\"))\n            + (TextRow(\"textrow7_ctx\")\n                +++ TextRow(\"textrow8_ctx\"))\n\n        XCTAssertEqual(form.count, 5)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(form[2].count, 2)\n\n        form +++ IntRow(\"introw1_ctx\")\n        form +++ IntRow(\"introw2_ctx\")\n            <<< IntRow(\"introw3_ctx\")\n            <<< IntRow(\"introw4_ctx\")\n\n        //      form:\n        //          text1\n        //          text2\n        //          -----\n        //          text3\n        //          text4\n        //          -----\n        //          text5\n        //          text6\n        //          -----\n        //          text7\n        //          -----\n        //          text8\n        //          -----\n        //          int1\n        //          ----\n        //          int2\n        //          int3\n        //          int4\n\n        XCTAssertEqual(form.count, 7)\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(form[2].count, 2)\n        XCTAssertEqual(form[3].count, 1)\n        XCTAssertEqual(form[4].count, 1)\n        XCTAssertEqual(form[5].count, 1)\n        XCTAssertEqual(form[6].count, 3)\n    }\n\n}\n"
  },
  {
    "path": "Tests/ResultBuildersTests.swift",
    "content": "//  ResultBuildersTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2022 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass ResultBuildersTests: BaseEurekaTests {\n    #if swift(>=5.4)\n    @SectionBuilder\n    var section1: Section {\n        NameRow(\"NameRow_f1\") { $0.title = \"Name\" }\n        if true {\n            IntRow(\"IntRow_f1\") { $0.title = \"Int\" }\n        }\n        DecimalRow(\"DecimalRow_f1\") { $0.title = \"Decimal\" }\n    }\n\n    @FormBuilder\n    var form: Form {\n        Section(\"Section A\") { section in\n            section.tag = \"Section_A\"\n        }\n        if true {\n            Section(\"Section B\") { section in\n                section.tag = \"Section_B\"\n            }\n        }\n        NameRow(\"NameRow_f1\") { $0.title = \"Name\" }\n    }\n    #endif\n\n    private var checkBuildEither = false\n    private var checkBuildExpressionBaseRowOptional = false\n\n    func testSectionBuilder() {\n        #if swift(>=5.4)\n        setupManySectionsForm()\n        addMoreItemsToManySectionsForm()\n\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"NameRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"IntRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"DecimalRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"UrlRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"TwitterRow_f1\"))\n        XCTAssertNil(manySectionsForm.rowBy(tag: \"TwitterRow_f2\"))\n        XCTAssertNil(manySectionsForm.rowBy(tag: \"EmailRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"AccountRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"PhoneRow_f1\"))\n        XCTAssertNil(manySectionsForm.rowBy(tag: \"PhoneRow_f2\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"ZipCodeRow_f1\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"PasswordRow_f1\"))\n        #endif\n    }\n\n    private func setupManySectionsForm() {\n        checkBuildEither = false\n        checkBuildExpressionBaseRowOptional = true\n        manySectionsForm = (section1 +++ {\n            URLRow(\"UrlRow_f1\") { $0.title = \"Url\" }\n            if checkBuildEither {\n                TwitterRow(\"TwitterRow_f2\") { $0.title = \"Twitter\" }\n            } else {\n                TwitterRow(\"TwitterRow_f1\") { $0.title = \"Twitter\" }\n            }\n            if checkBuildExpressionBaseRowOptional {\n                nil\n            } else {\n                EmailRow(\"EmailRow_f1\") { $0.title = \"Email\" }\n            }\n            AccountRow(\"AccountRow_f1\") { $0.title = \"Account\" }\n        })\n    }\n\n    private func addMoreItemsToManySectionsForm() {\n        checkBuildEither.toggle()\n        checkBuildExpressionBaseRowOptional.toggle()\n        manySectionsForm +++ {\n            if checkBuildEither {\n                PhoneRow(\"PhoneRow_f1\") { $0.title = \"Phone\" }\n            } else {\n                PhoneRow(\"PhoneRow_f2\") { $0.title = \"Phone\" }\n            }\n            if checkBuildExpressionBaseRowOptional {\n                nil\n            } else {\n                ZipCodeRow(\"ZipCodeRow_f1\") { $0.title = \"Zip Code\" }\n            }\n            PasswordRow(\"PasswordRow_f1\") { $0.title = \"Password\" }\n        }\n    }\n\n    func testFormBuilder() {\n        #if swift(>=5.4)\n        manySectionsForm = form\n        XCTAssertNotNil(manySectionsForm.sectionBy(tag: \"Section_A\"))\n        XCTAssertNotNil(manySectionsForm.sectionBy(tag: \"Section_B\"))\n        XCTAssertNotNil(manySectionsForm.rowBy(tag: \"NameRow_f1\"))\n        #endif\n    }\n}\n"
  },
  {
    "path": "Tests/RowByTagTests.swift",
    "content": "//  RowByTagTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass RowByTagTests: XCTestCase {\n\n    var form: Form!\n\n    override func setUp() {\n        super.setUp()\n\n        form = Form()\n        let section = Section()\n\n        form +++ section\n\n        section <<< LabelRow(\"LabelRow\")\n        section <<< ButtonRow(\"ButtonRow\")\n        section <<< ActionSheetRow<String>(\"ActionSheetRow\")\n        section <<< AlertRow<Int>(\"AlertRow\")\n        section <<< PushRow<URL>(\"PushRow\")\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n\n    func testRowByTag() {\n\n        let labelRow: LabelRow? = form.rowBy(tag: \"LabelRow\")\n        XCTAssertNotNil(labelRow)\n\n        let buttonRow: ButtonRow? = form.rowBy(tag: \"ButtonRow\")\n        XCTAssertNotNil(buttonRow)\n\n        let actionSheetRow: ActionSheetRow<String>? = form.rowBy(tag: \"ActionSheetRow\")\n        XCTAssertNotNil(actionSheetRow)\n\n        let alertRow: AlertRow<Int>? = form.rowBy(tag: \"AlertRow\")\n        XCTAssertNotNil(alertRow)\n\n        let pushRow: PushRow<URL>? = form.rowBy(tag: \"PushRow\")\n        XCTAssertNotNil(pushRow)\n    }\n\n}\n"
  },
  {
    "path": "Tests/RowCallbackTests.swift",
    "content": "//  RowCallbackTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass RowCallbackTests: BaseEurekaTests {\n\n    override func setUp() {\n        super.setUp()\n        formVC.form = Form()\n            +++ Section(\"something\")\n            <<< CheckRow(\"row1\").cellSetup { cell, _ in\n                cell.textLabel?.text = \"checkrow + Setup\"\n                cell.backgroundColor = .red\n            }\n            <<< IntRow(\"row2\").cellUpdate({ cell, _ in\n                cell.textLabel?.text = \"introw\"\n                cell.textLabel?.font = UIFont(name: \"Baskerville-Italic\", size: 20)\n            })\n            <<< TextRow(\"row3\").cellSetup({ cell, _ in\n                cell.textLabel?.text = \"aftersetup\"\n            }).cellUpdate({ cell, _ in\n                cell.textLabel?.text = \"afterupdate\"\n                cell.textLabel?.font = UIFont(name: \"Baskerville-Italic\", size: 20)\n            })\n    }\n\n    func testTableViewNotNil() {\n        XCTAssertNotNil(formVC.tableView)\n    }\n\n    func testOnChange() {\n        // Test onChange callback\n        let chk = CheckRow(\"row1\") { $0.title = \"check\"; $0.value = false }\n\n        formVC.form = Form()\n                        +++ Section(\"something\")\n                            <<< chk\n                            <<< IntRow(\"row2\") { $0.title = \"int\"; $0.value = 1 }\n                                .onChange { [weak chk] row in\n                                    chk?.value = ((row.value! % 2) == 0)\n                                }\n        let intRow = formVC.form[0][1]\n        intRow.baseValue = 2\n        XCTAssertEqual(chk.value, true)\n        formVC.form[0][1].baseValue = 3\n        XCTAssertEqual(chk.value, false)\n    }\n\n    func testCellSetupAndUpdate() {\n\n        let chkRow: CheckRow! = formVC.form.rowBy(tag: \"row1\")\n        let intRow: IntRow! = formVC.form.rowBy(tag: \"row2\")\n        let textRow: TextRow! = formVC.form.rowBy(tag: \"row3\")\n\n        // check that they all have indexPath\n        XCTAssertNotNil(chkRow.indexPath)\n        XCTAssertNotNil(intRow.indexPath)\n        XCTAssertNotNil(textRow.indexPath)\n\n        // make sure cellSetup is called for each cell\n\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: intRow.indexPath!)\n\n        XCTAssertEqual(chkRow.cell.textLabel?.text, \"checkrow + Setup\")\n        XCTAssertEqual(textRow.cell.textLabel?.text, \"aftersetup\")\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: textRow.indexPath!)\n        XCTAssertEqual(textRow.cell.textLabel?.text, \"afterupdate\")\n\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: chkRow.indexPath!)\n\n        //make sure cell update is called for each cell\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: chkRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: intRow.indexPath!)\n        let _ = formVC.tableView(formVC.tableView!, cellForRowAt: textRow.indexPath!)\n\n        XCTAssertEqual(chkRow?.cell.textLabel?.text, chkRow?.title)\n        XCTAssertEqual(intRow?.cell.textLabel?.text, \"introw\")\n        XCTAssertEqual(textRow?.cell.textLabel?.text, \"afterupdate\")\n\n        XCTAssertEqual(chkRow?.cell.backgroundColor, .red)\n        XCTAssertEqual(intRow?.cell.textLabel?.font, UIFont(name: \"Baskerville-Italic\", size: 20))\n        XCTAssertEqual(textRow?.cell.textLabel?.font, UIFont(name: \"Baskerville-Italic\", size: 20))\n\n    }\n}\n"
  },
  {
    "path": "Tests/RowsInsertionTests.swift",
    "content": "//\n//  RowsInsertionTests.swift\n//  Eureka\n//\n//  Created by Miguel Revetria on 5/8/17.\n//  Copyright © 2017 Xmartlabs. All rights reserved.\n//\n\nimport XCTest\n@testable import Eureka\n\nclass RowsInsertionTests: XCTestCase {\n    \n    func testAppendingRows() {\n        let form = Form()\n        let section = Section(\"section_01\")\n\n        form.append(section)\n        section.append(NameRow(tag: \"row_01\"))\n        section.append(NameRow(tag: \"row_02\"))\n        section.append(NameRow(tag: \"row_03\"))\n\n        hideAndShowRows(form: form, expectedTags: [\"row_01\", \"row_02\", \"row_03\"])\n    }\n\n    func testAppendingRowsWithCustomOperator() {\n        let form = Form()\n        let section = Section(\"section_01\")\n\n        form +++ section\n            <<< NameRow(tag: \"row_01\")\n            <<< NameRow(tag: \"row_02\")\n            <<< NameRow(tag: \"row_03\")\n\n        hideAndShowRows(form: form, expectedTags: [\"row_01\", \"row_02\", \"row_03\"])\n    }\n\n    func testInsertingRowsWithSubscript() {\n        let form = Form()\n        let section = Section(\"section_01\")\n\n        form[0] = section\n        form[0][0] = NameRow(tag: \"row_01\")\n        form[0][1] = NameRow(tag: \"row_02\")\n        form[0][2] = NameRow(tag: \"row_03\")\n\n        hideAndShowRows(form: form, expectedTags: [\"row_01\", \"row_02\", \"row_03\"])\n    }\n\n    func testMovingAppendedRows() {\n        let formInit: () -> Form = {\n            let form = Form()\n            let section = Section()\n\n            form.append(section)\n            section.append(NameRow(tag: \"tag_01\"))\n            section.append(NameRow(tag: \"tag_02\"))\n            section.append(NameRow(tag: \"tag_03\"))\n\n            return form\n        }\n\n        let append: (Section, BaseRow) -> Void = { section, row in\n            section.append(row)\n        }\n\n        movingRows(formInit: formInit, sectionAppend: append)\n    }\n\n    func testMovingAppendedRowsWithCustomOperator() {\n        let formInit: () -> Form = {\n            let form = Form()\n            let section = Section()\n\n            form +++ section\n            section <<< NameRow(tag: \"tag_01\")\n            section <<< NameRow(tag: \"tag_02\")\n            section <<< NameRow(tag: \"tag_03\")\n\n            return form\n        }\n\n        let append: (Section, BaseRow) -> Void = { section, row in\n            section <<< row\n        }\n\n        movingRows(formInit: formInit, sectionAppend: append)\n    }\n\n    func testMovingInsertedRowsWithSubscript() {\n        let formInit: () -> Form = {\n            let form = Form()\n            let section = Section()\n\n            form[0] = section\n            section[0] = NameRow(tag: \"tag_01\")\n            section[1] = NameRow(tag: \"tag_02\")\n            section[2] = NameRow(tag: \"tag_03\")\n\n            return form\n        }\n\n        let append: (Section, BaseRow) -> Void = { section, row in\n            section[section.count] = row\n        }\n\n        movingRows(formInit: formInit, sectionAppend: append)\n    }\n\n    func testReplacingAppendedRows() {\n        let form = Form()\n        let section = Section()\n\n        form.append(section)\n        section.append(NameRow(tag: \"tag_01\"))\n        section.append(NameRow(tag: \"tag_02\"))\n        section.append(NameRow(tag: \"tag_03\"))\n\n        replaceRows(form: form)\n    }\n\n    func testReplacingAppendedRowsWithCustomOperator() {\n        let form = Form()\n        let section = Section()\n\n        form +++ section\n            <<< NameRow(tag: \"tag_01\")\n            <<< NameRow(tag: \"tag_02\")\n            <<< NameRow(tag: \"tag_03\")\n\n        replaceRows(form: form)\n    }\n\n    func testReplacingInsertedRowsWithSubscript() {\n        let form = Form()\n        let section = Section()\n\n        form[0] = section\n        form[0][0] = NameRow(tag: \"tag_01\")\n        form[0][1] = NameRow(tag: \"tag_02\")\n        form[0][2] = NameRow(tag: \"tag_03\")\n\n        replaceRows(form: form)\n    }\n\n    func testReplacingSubrangeForAppendedRows() {\n        let form = Form()\n        let section = Section()\n\n        form.append(section)\n        section.append(NameRow(tag: \"tag_01\"))\n        section.append(NameRow(tag: \"tag_02\"))\n        section.append(NameRow(tag: \"tag_03\"))\n\n        replaceSectionSubranges(form: form)\n    }\n\n    func testReplacingSubrangeForAppendedRowsWithCustomOperator() {\n        let form = Form()\n        let section = Section()\n\n        form +++ section\n            <<< NameRow(tag: \"tag_01\")\n            <<< NameRow(tag: \"tag_02\")\n            <<< NameRow(tag: \"tag_03\")\n\n        replaceSectionSubranges(form: form)\n    }\n\n    func testReplacingSubrangeForInsertedRowsWithSubscript() {\n        let form = Form()\n        let section = Section()\n\n        form[0] = section\n        form[0][0] = NameRow(tag: \"tag_01\")\n        form[0][1] = NameRow(tag: \"tag_02\")\n        form[0][2] = NameRow(tag: \"tag_03\")\n        \n        replaceSectionSubranges(form: form)\n    }\n\n    private func hideAndShowRows(form: Form, expectedTags tags: [String]) {\n        form.first?.forEach { row in\n            XCTAssertNotNil(row.section)\n        }\n\n        XCTAssertEqual(form[0].count, 3)\n\n        var tag1 = form[0][0].tag!\n        var tag2 = form[0][1].tag!\n        var tag3 = form[0][2].tag!\n\n        XCTAssertEqual(tag1, tags[0])\n        XCTAssertEqual(tag2, tags[1])\n        XCTAssertEqual(tag3, tags[2])\n\n        var row = form[0][1]\n        row.hidden = true\n        row.evaluateHidden()\n        XCTAssertNotNil(row.section)\n\n        XCTAssertEqual(form[0].count, 2)\n        XCTAssertEqual(form.allRows.count, 3)\n\n        tag1 = form[0][0].tag!\n        tag3 = form[0][1].tag!\n        XCTAssertEqual(tag1, tags[0])\n        XCTAssertEqual(tag3, tags[2])\n\n        row = form[0][0]\n        row.hidden = true\n        row.evaluateHidden()\n        XCTAssertNotNil(row.section)\n\n        XCTAssertEqual(form[0].count, 1)\n        XCTAssertEqual(form.allRows.count, 3)\n\n        tag3 = form[0][0].tag!\n        XCTAssertEqual(tag3, tags[2])\n\n        row = form[0][0]\n        row.hidden = true\n        row.evaluateHidden()\n        XCTAssertNotNil(row.section)\n\n        XCTAssertEqual(form[0].count, 0)\n        XCTAssertEqual(form.allRows.count, 3)\n\n        form.allRows\n            .map { $0.tag! }\n            .enumerated()\n            .forEach { ind, tag in\n                XCTAssertEqual(tag, tags[ind])\n            }\n\n        form.allRows[1].hidden = false\n        form.allRows[1].evaluateHidden()\n\n        XCTAssertEqual(form[0].count, 1)\n        XCTAssertEqual(form.allRows.count, 3)\n\n        tag2 = form[0][0].tag!\n        XCTAssertEqual(tag2, tags[1])\n    }\n\n    private func movingRows(formInit: () -> Form, sectionAppend: (Section, BaseRow) -> Void) {\n        var form = formInit()\n\n        var tmp = form[0].remove(at: 0)\n        XCTAssertNil(tmp.section)\n        sectionAppend(form[0], tmp)\n        XCTAssertNotNil(tmp.section)\n\n        hideAndShowRows(form: form, expectedTags: [\"tag_02\", \"tag_03\", \"tag_01\"])\n\n        form = formInit()\n        tmp = form[0].remove(at: 1)\n        XCTAssertNil(tmp.section)\n        sectionAppend(form[0], tmp)\n        XCTAssertNotNil(tmp.section)\n\n        hideAndShowRows(form: form, expectedTags: [\"tag_01\", \"tag_03\", \"tag_02\"])\n\n        form = formInit()\n        tmp = form[0].remove(at: 2)\n        XCTAssertNil(tmp.section)\n        sectionAppend(form[0], tmp)\n        XCTAssertNotNil(tmp.section)\n\n        hideAndShowRows(form: form, expectedTags: [\"tag_01\", \"tag_02\", \"tag_03\"])\n    }\n\n    private func replaceRows(form: Form) {\n        let section = form.first!\n        for ind in 0..<section.count {\n            let testTag = \"tag_test_0\\(ind)\"\n            let testRow = NameRow(tag: testTag)\n            let row = section[ind]\n\n            XCTAssertNotNil(row.section)\n            section[ind] = testRow\n\n            XCTAssertNotNil(testRow.section)\n            XCTAssertNil(row.section)\n            XCTAssertEqual(section[ind].tag!, testTag)\n        }\n    }\n\n    private func replaceSectionSubranges(form: Form) {\n        let section = form.first!\n        let row = section.first!\n        let testRow = NameRow(tag: \"tag_test_01\")\n        let testRow2 = NameRow(tag: \"tag_test_02\")\n\n        XCTAssertNotNil(row.section)\n        section.replaceSubrange(0..<1, with: [testRow])\n        XCTAssertNotNil(testRow.section)\n        XCTAssertNil(row.section)\n        XCTAssertEqual(section.count, 3)\n\n        section.replaceSubrange(0..<1, with: [])\n        XCTAssertNil(testRow.section)\n        XCTAssertEqual(section.count, 2)\n\n        section.replaceSubrange(0..<1, with: [testRow, testRow2])\n        XCTAssertNotNil(testRow.section)\n        XCTAssertNotNil(testRow2.section)\n        XCTAssertEqual(section.count, 3)\n\n        section.replaceSubrange(0..<section.count, with: [])\n        XCTAssertNil(testRow.section)\n        XCTAssertNil(testRow2.section)\n        XCTAssertTrue(section.isEmpty)\n    }\n\n}\n"
  },
  {
    "path": "Tests/SectionsInsertionTests.swift",
    "content": "//\n//  SectionInsertionTests.swift\n//  Eureka\n//\n//  Created by Miguel Revetria on 5/8/17.\n//  Copyright © 2017 Xmartlabs. All rights reserved.\n//\n\nimport XCTest\n@testable import Eureka\n\nclass SectionInsertionTests: XCTestCase {\n\n    var formVC = FormViewController()\n    var form: Form!\n\n    func testAppendingSections() {\n        let form = Form()\n        form.append(Section(\"section_01\"))\n        form.append(Section(\"section_02\"))\n        form.append(Section(\"section_03\"))\n\n        hideAndShowSections(\n            form: form,\n            expectedTitles: [\"section_01\", \"section_02\", \"section_03\"]\n        )\n    }\n\n    func testAppendingSectionsWithCustomOperator() {\n        let form = Form()\n        form +++ Section(\"section_01\")\n        form +++ Section(\"section_02\")\n        form +++ Section(\"section_03\")\n\n        hideAndShowSections(\n            form: form,\n            expectedTitles: [\"section_01\", \"section_02\", \"section_03\"]\n        )\n    }\n\n    func testInsertingSectionsWithSubscript() {\n        let form = Form()\n        form[0] = Section(\"section_01\")\n        form[1] = Section(\"section_02\")\n        form[2] = Section(\"section_03\")\n\n        hideAndShowSections(\n            form: form,\n            expectedTitles: [\"section_01\", \"section_02\", \"section_03\"]\n        )\n    }\n\n    func testMovingAppendedSections() {\n        let formInit: () -> Form = {\n            let form = Form()\n            form.append(Section(\"section_01\"))\n            form.append(Section(\"section_02\"))\n            form.append(Section(\"section_03\"))\n            return form\n        }\n\n        let append: (Form, Section) -> Void = { form, section in\n            form.append(section)\n        }\n\n        movingSections(formInit: formInit, formAppend: append)\n    }\n\n    func testMovingAppendedSectionsWithCustomOperator() {\n        let formInit: () -> Form = {\n            let form = Form()\n            form +++ Section(\"section_01\")\n            form +++ Section(\"section_02\")\n            form +++ Section(\"section_03\")\n            return form\n        }\n\n        let append: (Form, Section) -> Void = { form, section in\n            form +++ section\n        }\n\n        movingSections(formInit: formInit, formAppend: append)\n    }\n\n    func testMovingInsertedSectionsWithSubscript() {\n        let formInit: () -> Form = {\n            let form = Form()\n            form[0] = Section(\"section_01\")\n            form[1] = Section(\"section_02\")\n            form[2] = Section(\"section_03\")\n            return form\n        }\n\n        let append: (Form, Section) -> Void = { form, section in\n            form[form.count] = section\n        }\n\n        movingSections(formInit: formInit, formAppend: append)\n    }\n\n    func testReplacingAppendedSections() {\n        let form = Form()\n        form.append(Section(\"section_01\"))\n        form.append(Section(\"section_02\"))\n        form.append(Section(\"section_03\"))\n\n        replaceSections(form: form)\n    }\n\n    func testReplacingAppendedSectionsWithCustomOperator() {\n        let form = Form()\n        form +++ Section(\"section_01\")\n        form +++ Section(\"section_02\")\n        form +++ Section(\"section_03\")\n\n        replaceSections(form: form)\n    }\n\n    func testReplacingInsertedSectionsWithSubscript() {\n        let form = Form()\n        form[0] = Section(\"section_01\")\n        form[1] = Section(\"section_02\")\n        form[2] = Section(\"section_03\")\n\n        replaceSections(form: form)\n    }\n\n    func testReplacingSubrangeForAppendedSections() {\n        let form = Form()\n        form.append(Section(\"section_01\"))\n        form.append(Section(\"section_02\"))\n        form.append(Section(\"section_03\"))\n\n        replaceSectionSubranges(form: form)\n    }\n\n    func testReplacingSubrangeForAppendedSectionsWithCustomOperator() {\n        let form = Form()\n        form +++ Section(\"section_01\")\n        form +++ Section(\"section_02\")\n        form +++ Section(\"section_03\")\n\n        replaceSectionSubranges(form: form)\n    }\n\n    func testReplacingSubrangeForInsertedSectionsWithSubscript() {\n        let form = Form()\n        form[0] = Section(\"section_01\")\n        form[1] = Section(\"section_02\")\n        form[2] = Section(\"section_03\")\n\n        replaceSectionSubranges(form: form)\n    }\n\n    func testInsertingAfterRow() {\n        let form = Form()\n        form[0] = Section(\"section_01\")\n        form[0] <<< TextRow(\"a\")\n            <<< TextRow(\"b\") { $0.hidden = true }\n            <<< TextRow(\"d\") { $0.hidden = true }\n            <<< TextRow(\"e\")\n\n        let bRow = form.rowBy(tag: \"b\")\n        XCTAssertNotNil(bRow)\n\n        try? form[0].insert(row: TextRow(\"c\"), after: bRow!)\n\n        let cRow = form.rowBy(tag: \"c\")\n        XCTAssertNotNil(cRow)\n\n        XCTAssertEqual(form[0].count, 3) // a, c, e\n        XCTAssertEqual(form.allRows.count, 5) // a, b, c, d, e\n        XCTAssertEqual(form[0][1], cRow)\n    }\n\n    func testInsertingAfterRowAtEnd() {\n        let form = Form()\n        form[0] = Section(\"section_01\")\n        form[0] <<< TextRow(\"a\") { $0.hidden = true }\n\n        let aRow = form.rowBy(tag: \"a\")\n        XCTAssertNotNil(aRow)\n\n        try? form[0].insert(row: TextRow(\"b\") { $0.hidden = true }, after: aRow!)\n\n        let bRow = form.rowBy(tag: \"b\")\n        XCTAssertNotNil(bRow)\n\n        XCTAssertEqual(form[0].count, 0)\n        XCTAssertEqual(form.allRows.count, 2) // a, b\n\n        try? form[0].insert(row: TextRow(\"c\"), after: aRow!)\n\n        let cRow = form.rowBy(tag: \"c\")\n        XCTAssertNotNil(cRow)\n\n        XCTAssertEqual(form[0].count, 1) // c\n        XCTAssertEqual(form.allRows.count, 3) // a, c, b\n        XCTAssertEqual(form.allRows[0], aRow)\n        XCTAssertEqual(form.allRows[1], cRow)\n        XCTAssertEqual(form.allRows[2], bRow)\n    }\n\n    func testDeletingRows() {\n        let form = Form()\n        let section = Section(\"section_01\")\n        form.append(section)\n\n        section.append(NameRow(tag: \"row_01\"))\n        section.append(NameRow(tag: \"row_2\"))\n        section.append(NameRow(\"row_03\") { $0.hidden = true })\n        section.append(NameRow(\"row_04\") { $0.hidden = true })\n\n        section.removeAll(where: { row in row.tag?.hasPrefix(\"row_0\") ?? false })\n        XCTAssertNotNil(form.rowBy(tag: \"row_2\"))\n        XCTAssertEqual(form.allRows.count, 1)\n    }\n\n    func testDeletingSections() {\n        let form = Form()\n        form +++ Section(\"section_0\")\n            +++ Section(\"section_1\") { $0.hidden = true }\n            +++ Section(\"section_22\")\n            +++ Section(\"section_32\")\n\n        form.removeAll(where: { section in section.header?.title?.hasSuffix(\"2\") ?? false })\n        XCTAssertEqual(form.allSections.count, 2)        \n    }\n\n    func testReplaceAllSection() {\n        let form = Form() +++ Section(\"section1\") {\n            $0.hidden = true\n        }\n            +++ Section(\"section2\")\n            +++ Section(\"section3\")\n\n        form.replaceSubrangeInAllSections(Range<Int>(uncheckedBounds: (lower: 0, upper: 2)), with: [Section(\"section0\") { $0.hidden = true }])\n\n        XCTAssertEqual(form.allSections.count, 2)\n        XCTAssertEqual(form.count, 1)\n        XCTAssertEqual(form[0].header?.title, \"section3\")\n        XCTAssertEqual(form.allSections[0].header?.title, \"section0\")\n        XCTAssertEqual(form.allSections[1].header?.title, \"section3\")\n    }\n\n\n    private func hideAndShowSections(form: Form, expectedTitles titles: [String]) {\n        // Doesn't matter how rows were added to the form (using append, +++ or subscript index)\n        // next must work\n\n        XCTAssertEqual(form.count, 3)\n\n        var title1 = form[0].header!.title!\n        var title2 = form[1].header!.title!\n        var title3 = form[2].header!.title!\n\n        XCTAssertEqual(title1, titles[0])\n        XCTAssertEqual(title2, titles[1])\n        XCTAssertEqual(title3, titles[2])\n\n        var sect = form[1]\n        sect.hidden = true\n        sect.evaluateHidden()\n        XCTAssertNotNil(sect.form)\n\n        XCTAssertEqual(form.count, 2)\n        XCTAssertEqual(form.allSections.count, 3)\n\n        title1 = form[0].header!.title!\n        title3 = form[1].header!.title!\n        XCTAssertEqual(title1, titles[0])\n        XCTAssertEqual(title3, titles[2])\n\n        sect = form[0]\n        sect.hidden = true\n        sect.evaluateHidden()\n        XCTAssertNotNil(sect.form)\n\n        XCTAssertEqual(form.count, 1)\n        XCTAssertEqual(form.allSections.count, 3)\n\n        title3 = form[0].header!.title!\n        XCTAssertEqual(title3, titles[2])\n\n        sect = form[0]\n        sect.hidden = true\n        sect.evaluateHidden()\n        XCTAssertNotNil(sect.form)\n\n        XCTAssertEqual(form.count, 0)\n        XCTAssertEqual(form.allSections.count, 3)\n\n        form.allSections\n            .map { $0.header!.title! }\n            .enumerated()\n            .forEach { ind, title in\n                XCTAssertEqual(title, titles[ind])\n            }\n\n        form.allSections[1].hidden = false\n        form.allSections[1].evaluateHidden()\n\n        XCTAssertEqual(form.count, 1)\n        XCTAssertEqual(form.allSections.count, 3)\n\n        title2 = form[0].header!.title!\n        XCTAssertEqual(title2, titles[1])\n    }\n\n    private func movingSections(formInit: () -> Form, formAppend: (Form, Section) -> Void) {\n        var form = formInit()\n        var tmp = form.remove(at: 0)\n        XCTAssertNil(tmp.form)\n        formAppend(form, tmp)\n        XCTAssertNotNil(tmp.form)\n\n        hideAndShowSections(form: form, expectedTitles: [\"section_02\", \"section_03\", \"section_01\"])\n\n        form = formInit()\n        tmp = form.remove(at: 1)\n        XCTAssertNil(tmp.form)\n        formAppend(form, tmp)\n        XCTAssertNotNil(tmp.form)\n\n        hideAndShowSections(form: form, expectedTitles: [\"section_01\", \"section_03\", \"section_02\"])\n\n        form = formInit()\n        tmp = form.remove(at: 2)\n        XCTAssertNil(tmp.form)\n        formAppend(form, tmp)\n        XCTAssertNotNil(tmp.form)\n\n        hideAndShowSections(form: form, expectedTitles: [\"section_01\", \"section_02\", \"section_03\"])\n    }\n\n    private func replaceSections(form: Form) {\n        for ind in 0..<form.count {\n            let testTitle = \"section_test_\\(ind)\"\n            let testSection = Section(testTitle)\n            let section = form[ind]\n\n            XCTAssertNotNil(section.form)\n            form[ind] = testSection\n\n            XCTAssertNotNil(testSection.form)\n            XCTAssertNil(section.form)\n            XCTAssertEqual(form[ind].header!.title!, testTitle)\n        }\n    }\n\n    private func replaceSectionSubranges(form: Form) {\n        let section = form.first!\n        let testSection = Section(\"section_test_01\")\n        let testSection2 = Section(\"section_test_02\")\n\n        XCTAssertNotNil(section.form)\n        form.replaceSubrange(0..<1, with: [testSection])\n        XCTAssertNotNil(testSection.form)\n        XCTAssertNil(section.form)\n        XCTAssertEqual(form.count, 3)\n\n        form.replaceSubrange(0..<1, with: [])\n        XCTAssertNil(testSection.form)\n        XCTAssertEqual(form.count, 2)\n\n        form.replaceSubrange(0..<1, with: [testSection, testSection2])\n        XCTAssertNotNil(testSection.form)\n        XCTAssertNotNil(testSection2.form)\n        XCTAssertEqual(form.count, 3)\n\n        form.replaceSubrange(0..<form.count, with: [])\n        XCTAssertNil(testSection.form)\n        XCTAssertNil(testSection2.form)\n        XCTAssertTrue(form.isEmpty)\n    }\n\n}\n"
  },
  {
    "path": "Tests/SelectableSectionTests.swift",
    "content": "//  SelectableSectionTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass SelectableSectionTests: XCTestCase {\n\n    var formVC = FormViewController()\n\n    override func setUp() {\n        super.setUp()\n        let form = Form()\n        //create a form with two sections. The second one is of multiple selection\n\n        let continents = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\n        let oceans = [\"Arctic\", \"Atlantic\", \"Indian\", \"Pacific\", \"Southern\"]\n\n        form +++ SelectableSection<ListCheckRow<String>> { _ in }\n        for option in continents {\n            form.last! <<< ListCheckRow<String>(option) { lrow in\n                lrow.title = option\n                lrow.selectableValue = option\n                lrow.value = nil\n            }\n        }\n\n        form +++ SelectableSection<ListCheckRow<String>>(\"And which of the following oceans have you taken a bath in?\", selectionType: .multipleSelection)\n        for option in oceans {\n            form.last! <<< ListCheckRow<String>(option) { lrow in\n                lrow.title = option\n                lrow.selectableValue = option\n            }\n        }\n\n        form +++ SelectableSection<ListCheckRow<String>>(\"\", selectionType: .singleSelection(enableDeselection: false))\n        for option in oceans {\n            form.last! <<< ListCheckRow<String>(\"\\(option)2\") { lrow in\n                lrow.title = option\n                lrow.selectableValue = option\n            }\n        }\n        formVC.form = form\n\n        // load the view to test the cells\n        formVC.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        formVC.tableView?.frame = formVC.view.frame\n    }\n\n    override func tearDown() {\n        super.tearDown()\n    }\n\n    func testSections() {\n\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 1, section: 0))\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 1, section: 1))\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 3, section: 1))\n\n        let value1 = (formVC.form[0] as! SelectableSection<ListCheckRow<String>>).selectedRow()?.baseValue\n        let value2 = (formVC.form[1] as! SelectableSection<ListCheckRow<String>>).selectedRows().map {$0.baseValue}\n\n        XCTAssertEqual(value1 as! String, \"Antarctica\")\n        XCTAssertTrue(value2.count == 2)\n        XCTAssertEqual((value2[0] as! String), \"Atlantic\")\n        XCTAssertEqual((value2[1] as! String), \"Pacific\")\n\n        //Now deselect One of the multiple selection section and change the value of the first section\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 6, section: 0))\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 1, section: 1))\n\n\n        let value3 = (formVC.form[0] as! SelectableSection<ListCheckRow<String>>).selectedRow()?.baseValue\n        \n        let selectedRows = (formVC.form[1] as! SelectableSection<ListCheckRow<String>>).selectedRows()\n        let value4 = selectedRows.map { $0.baseValue }\n\n        XCTAssertEqual(value3 as! String, \"South America\")\n        XCTAssertTrue(value4.count == 1)\n        XCTAssertEqual((value4[0] as! String), \"Pacific\")\n    }\n\n    func testDeselectionDisabled() {\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 0, section: 2))\n\n        var value1 = (formVC.form[2] as! SelectableSection<ListCheckRow<String>>).selectedRow()?.baseValue\n\n        XCTAssertEqual(value1 as? String, \"Arctic\")\n\n        // now try deselecting one of each and see that nothing changes.\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 0, section: 2))\n\n        value1 = (formVC.form[2] as! SelectableSection<ListCheckRow<String>>).selectedRow()?.baseValue\n\n        XCTAssertEqual(value1 as? String, \"Arctic\")\n\n        // But we can change the value in the first section\n        formVC.tableView(formVC.tableView!, didSelectRowAt: IndexPath(row: 2, section: 2))\n\n        value1 = (formVC.form[2] as! SelectableSection<ListCheckRow<String>>).selectedRow()?.baseValue\n\n        XCTAssertEqual(value1 as? String, \"Indian\")\n\n    }\n\n    func testSectionedSections() {\n        let selectorViewController = SelectorViewController<PushRow<String>>(nibName: nil, bundle: nil)\n        selectorViewController.row = PushRow<String> { row in\n            row.options = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\n        }\n        enum Hemisphere: Int {\n            case west, east, none\n        }\n\n        selectorViewController.sectionKeyForValue = { option in\n            switch option {\n            case \"Africa\", \"Asia\", \"Australia\", \"Europe\":\n                return String(Hemisphere.west.rawValue)\n            case \"North America\", \"South America\":\n                return String(Hemisphere.east.rawValue)\n            default:\n                return String(Hemisphere.none.rawValue)\n            }\n        }\n        selectorViewController.sectionHeaderTitleForKey = { key in\n            switch Hemisphere(rawValue: Int(key)!)! {\n            case .west: return \"West hemisphere\"\n            case .east: return \"East hemisphere\"\n            case .none: return \"\"\n            }\n        }\n        selectorViewController.sectionFooterTitleForKey = { key in\n            switch Hemisphere(rawValue: Int(key)!)! {\n            case .west: return \"West hemisphere\"\n            case .east: return \"East hemisphere\"\n            case .none: return \"\"\n            }\n        }\n\n        selectorViewController.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        selectorViewController.tableView?.frame = selectorViewController.view.frame\n\n        let form = selectorViewController.form\n\n        XCTAssertEqual(form.count, 3)\n        XCTAssertEqual(form[0].count, 4)\n        XCTAssertEqual(form[1].count, 2)\n        XCTAssertEqual(form[2].count, 1)\n\n        XCTAssertEqual(form[0].header?.title, \"West hemisphere\")\n        XCTAssertEqual(form[1].header?.title, \"East hemisphere\")\n        XCTAssertEqual(form[2].header?.title, \"\")\n\n        XCTAssertEqual(form[0].footer?.title, \"West hemisphere\")\n        XCTAssertEqual(form[1].footer?.title, \"East hemisphere\")\n        XCTAssertEqual(form[2].footer?.title, \"\")\n\n        XCTAssertEqual(form[0].compactMap({ ($0 as! ListCheckRow<String>).selectableValue }), [\"Africa\", \"Asia\", \"Australia\", \"Europe\"])\n        XCTAssertEqual(form[1].compactMap({ ($0 as! ListCheckRow<String>).selectableValue }), [\"North America\", \"South America\"])\n        XCTAssertEqual(form[2].compactMap({ ($0 as! ListCheckRow<String>).selectableValue }), [\"Antarctica\"])\n    }\n\n    func testLazyOptionsProvider() {\n        let selectorViewController = SelectorViewController<PushRow<String>>(nibName: nil, bundle: nil)\n        let row = PushRow<String>()\n        selectorViewController.row = row\n        let options = [\"Africa\", \"Antarctica\", \"Asia\", \"Australia\", \"Europe\", \"North America\", \"South America\"]\n        \n        let optionsFetched = expectation(description: \"Fetched options\")\n        row.optionsProvider = .lazy({ form, completion in\n            DispatchQueue.main.async {\n                completion(options)\n                optionsFetched.fulfill()\n            }\n        })\n\n        let form = selectorViewController.form\n        \n        XCTAssertEqual(form.count, 0)\n\n        selectorViewController.view.frame = CGRect(x: 0, y: 0, width: 375, height: 3000)\n        selectorViewController.tableView?.frame = selectorViewController.view.frame\n        \n        waitForExpectations(timeout: 1, handler: nil)\n        \n        XCTAssertEqual(row.options ?? [], options)\n        XCTAssertEqual(form.count, 1)\n        XCTAssertEqual(form[0].count, options.count)\n        XCTAssertEqual(form[0].compactMap({ ($0 as! ListCheckRow<String>).selectableValue }), options)\n    }\n    \n}\n"
  },
  {
    "path": "Tests/SetValuesTests.swift",
    "content": "//  SetValuesTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass SetValuesTests: XCTestCase {\n\n    var form: Form!\n\n    override func setUp() {\n        super.setUp()\n\n        form = Form()\n        let section = Section()\n\n        form +++ section\n\n        section <<< IntRow(\"IntRow\")\n        section <<< TextRow(\"TextRow\")\n        section <<< ActionSheetRow<String>(\"ActionSheetRow\")\n        section <<< AlertRow<Int>(\"AlertRow\")\n        section <<< PushRow<Float>(\"PushRow\")\n\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n\n    func testSetValues() {\n        let intRowValue: Int = 4\n        let intRowNilValue: Int? = nil\n        let textRowValue = \"textRow value!!!\"\n        let actionSheetRowValue = \"ActionSheetRow value!!!\"\n        let alertRowValue: Int = 33\n        let pushRowValue: Float = 0.7\n\n        form.setValues([\"IntRow\": intRowValue, \"TextRow\": textRowValue, \"ActionSheetRow\": actionSheetRowValue, \"AlertRow\": alertRowValue, \"PushRow\": pushRowValue, \"No existing tag\": 2.0])\n\n        let intRow: IntRow? = form.rowBy(tag: \"IntRow\")\n        XCTAssertEqual(intRow?.value, intRowValue)\n\n        let textRow: TextRow? = form.rowBy(tag: \"TextRow\")\n        XCTAssertEqual(textRow?.value, textRowValue)\n\n        let actionSheetRow: ActionSheetRow<String>? = form.rowBy(tag: \"ActionSheetRow\")\n        XCTAssertEqual(actionSheetRow?.value, actionSheetRowValue)\n\n        let alertRow: AlertRow<Int>? = form.rowBy(tag: \"AlertRow\")\n        XCTAssertNotNil(alertRow)\n        XCTAssertEqual(alertRow!.value, alertRowValue)\n\n        var pushRow: PushRow<Float>? = form.rowBy(tag: \"PushRow\")\n        XCTAssertNotNil(pushRow)\n        XCTAssertEqual(pushRow!.value, pushRowValue)\n\n        form.setValues([\"PushRow\": Float(1.0), \"No existing tag\": 2.0])\n        pushRow = form.rowBy(tag: \"PushRow\")\n        XCTAssertNotNil(pushRow)\n        XCTAssertEqual(pushRow!.value, Float(1.0))\n\n        form.setValues([\"IntRow\": intRowNilValue])\n        XCTAssertNil(intRow?.value)\n    }\n    \n    // The reset value stores the default value of the row. The reset value should not change along with the value property, and when you reset the row value, it should set the value property to the reset value.\n    func testSetAndResetValues() {\n        let intValue: Int = 4\n        let intDefaultvalue: Int = 0\n        let stringValue = \"String Value!\"\n        let stringDefaultValue = \"String Default Value!\"\n        let floatValue: Float = 0.7\n        let floatDefaultValue: Float = 1.4\n        \n        let intRow: IntRow? = form.rowBy(tag: \"IntRow\")\n        XCTAssertNotNil(intRow)\n        intRow?.resetValue = intDefaultvalue\n        XCTAssertEqual(intRow?.resetValue, intDefaultvalue)\n        intRow?.value = intValue\n        intRow?.resetRowValue()\n        XCTAssertEqual(intRow?.value, intDefaultvalue)\n        \n        let textRow: TextRow? = form.rowBy(tag: \"TextRow\")\n        XCTAssertNotNil(textRow)\n        textRow?.resetValue = stringDefaultValue\n        XCTAssertEqual(textRow?.resetValue, stringDefaultValue)\n        textRow?.value = stringValue\n        textRow?.resetRowValue()\n        XCTAssertEqual(textRow?.value, stringDefaultValue)\n        \n        let actionSheetRow: ActionSheetRow<String>? = form.rowBy(tag: \"ActionSheetRow\")\n        XCTAssertNotNil(actionSheetRow)\n        actionSheetRow?.resetValue = stringDefaultValue\n        XCTAssertEqual(actionSheetRow?.resetValue, stringDefaultValue)\n        actionSheetRow?.value = stringValue\n        actionSheetRow?.resetRowValue()\n        XCTAssertEqual(actionSheetRow?.value, stringDefaultValue)\n        \n        let alertRow: AlertRow<Int>? = form.rowBy(tag: \"AlertRow\")\n        XCTAssertNotNil(alertRow)\n        alertRow?.resetValue = intDefaultvalue\n        XCTAssertEqual(alertRow?.resetValue, intDefaultvalue)\n        alertRow?.value = intValue\n        alertRow?.resetRowValue()\n        XCTAssertEqual(alertRow?.value, intDefaultvalue)\n        \n        let pushRow: PushRow<Float>? = form.rowBy(tag: \"PushRow\")\n        XCTAssertNotNil(pushRow)\n        pushRow?.resetValue = floatDefaultValue\n        XCTAssertEqual(pushRow?.resetValue, floatDefaultValue)\n        pushRow?.value = floatValue\n        pushRow?.resetRowValue()\n        XCTAssertEqual(pushRow?.value, floatDefaultValue)\n        \n    }\n}\n"
  },
  {
    "path": "Tests/ValidationsTests.swift",
    "content": "//  ValidationsTests.swift\n//  Eureka ( https://github.com/xmartlabs/Eureka )\n//\n//  Copyright (c) 2016 Xmartlabs SRL ( http://xmartlabs.com )\n//\n//\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n//\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n//\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n// THE SOFTWARE.\n\nimport XCTest\n@testable import Eureka\n\nclass ValidationsTests: XCTestCase {\n    override func setUp() {\n        super.setUp()\n        // Put setup code here. This method is called before the invocation of each test method in the class.\n    }\n\n    override func tearDown() {\n        // Put teardown code here. This method is called after the invocation of each test method in the class.\n        super.tearDown()\n    }\n\n    func testadd() {\n        let textRow = TextRow()\n        textRow.add(rule: RuleRequired())\n        textRow.add(rule: RuleEmail())\n        XCTAssertEqual(textRow.rules.count, 2)\n\n        textRow.removeAllRules()\n        XCTAssertEqual(textRow.rules.count, 0)\n    }\n\n    func testRuleSet() {\n        var ruleSet = RuleSet<String>()\n        ruleSet.add(rule: RuleRequired())\n        ruleSet.add(rule: RuleEmail())\n        XCTAssertEqual(ruleSet.rules.count, 2)\n\n        let textRow = TextRow()\n        textRow.add(ruleSet: ruleSet)\n\n        XCTAssertEqual(textRow.rules.count, 2)\n    }\n\n    func testRemoveRules() {\n        let textRow = TextRow()\n        textRow.add(rule: RuleRequired())\n        textRow.add(rule: RuleEmail())\n        XCTAssertEqual(textRow.rules.count, 2)\n\n        textRow.removeAllRules()\n        XCTAssertEqual(textRow.rules.count, 0)\n\n        var requiredRule = RuleRequired<String>()\n        requiredRule.id = \"required_rule_id\"\n        textRow.add(rule: requiredRule)\n        textRow.add(rule: RuleEmail())\n        XCTAssertEqual(textRow.rules.count, 2)\n\n        textRow.remove(ruleWithIdentifier: \"required_rule_id\")\n        XCTAssertEqual(textRow.rules.count, 1)\n    }\n\n    func testBlurred() {\n        let formVC = FormViewController(style: .grouped)\n        let row = TextRow()\n        row.add(rule: RuleRequired())\n        XCTAssertFalse(row.wasBlurred)\n        formVC.form +++ row\n        formVC.endEditing(of: row.cell)\n        XCTAssertTrue(row.wasBlurred)\n    }\n\n    func testUsed() {\n        let formVC = FormViewController(style: .grouped)\n        let row = TextRow()\n        row.add(rule: RuleRequired())\n        XCTAssertFalse(row.wasChanged)\n        row.value = \"Hi!\"\n        XCTAssertFalse(row.wasChanged) // because it's not added in the form yet\n        formVC.form +++ row\n        row.value = \"Eureka!\"\n        XCTAssertTrue(row.wasChanged) // because it was added to the form\n    }\n\n    func testRequired() {\n        let textRow = TextRow()\n        textRow.add(rule: RuleRequired())\n\n        textRow.value = nil\n        XCTAssertTrue(textRow.validate().count == 1, \"errors collection must contains Required rule error\")\n\n        textRow.value = \"Hi1\"\n        XCTAssertTrue(textRow.validate().count == 0, \"errors collection must not contains Required rule error\")\n    }\n\n    func testRuleEmail() {\n        let emailRule = RuleEmail()\n\n        XCTAssertNil(emailRule.isValid(value: nil))\n        XCTAssertNil(emailRule.isValid(value: \"\"))\n        XCTAssertNil(emailRule.isValid(value: \"a@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a!omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a?omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a#omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a$omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a%omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a'omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a`omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a*omalley@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a/omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a=omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a~omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a^omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a/omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a{omally@b.com\"))\n        XCTAssertNil(emailRule.isValid(value: \"a}omally@b.com\"))\n        \n        XCTAssertNotNil(emailRule.isValid(value: \"abc\"))\n        XCTAssertNotNil(emailRule.isValid(value: \"abc.com\"))\n        XCTAssertNotNil(emailRule.isValid(value: \"abc@assa\"))\n        XCTAssertNotNil(emailRule.isValid(value: \"a&b@b.com\"))\n        XCTAssertNotNil(emailRule.isValid(value: \"a[omalley@b.com\"))\n        XCTAssertNotNil(emailRule.isValid(value: \"a]omalley@b.com\"))\n    }\n\n    func testMaxLengthRule() {\n        let maxLengthRule = RuleMaxLength(maxLength: 10)\n        XCTAssertNil(maxLengthRule.isValid(value: nil))\n        XCTAssertNil(maxLengthRule.isValid(value: \"123456789\"))\n        XCTAssertNotNil(maxLengthRule.isValid(value:\"12345678910\"))\n    }\n\n    func testMinLengthRule() {\n        let minLengthRule = RuleMinLength(minLength: 5)\n        XCTAssertNil(minLengthRule.isValid(value: nil))\n        XCTAssertNil(minLengthRule.isValid(value: \"12345\"))\n        XCTAssertNotNil(minLengthRule.isValid(value:\"1234\"))\n    }\n    \n    func testExactLengthRule() {\n        let exactLengthRule = RuleExactLength(exactLength: 3)\n        XCTAssertNil(exactLengthRule.isValid(value: nil))\n        XCTAssertNil(exactLengthRule.isValid(value: \"123\"))\n        XCTAssertNotNil(exactLengthRule.isValid(value:\"1234\"))\n    }\n    \n    func testRuleURL() {\n        let urlRule = RuleURL()\n        \n        XCTAssertNil(urlRule.isValid(value: nil))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"http://example.com\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"http://to.co\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"https://example.com/path/to/file.ext?key=value#location\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"https://example.com:8080/path/to/file.ext?key=value#location\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"https://localhost\")))\n        XCTAssertNil(urlRule.isValid(value: URL(string: \"https://localhost:8080\")))\n\n        XCTAssertNotNil(urlRule.isValid(value: URL(string: \"example.com\")))\n        XCTAssertNotNil(urlRule.isValid(value: URL(string: \"www.example.com\")))\n        XCTAssertNotNil(urlRule.isValid(value: URL(string: \"http://\")))\n    }\n}\n"
  }
]