{"id":32323443,"url":"https://github.com/unboxme/pureform","last_synced_at":"2025-10-23T12:56:07.682Z","repository":{"id":62451286,"uuid":"68051499","full_name":"unboxme/PureForm","owner":"unboxme","description":null,"archived":false,"fork":false,"pushed_at":"2016-12-04T14:01:33.000Z","size":157,"stargazers_count":20,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-10-23T12:56:06.454Z","etag":null,"topics":["forms","json","prototype","storyboard","tableview","validation","xcode"],"latest_commit_sha":null,"homepage":null,"language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/unboxme.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-09-12T21:57:02.000Z","updated_at":"2023-06-07T13:30:14.000Z","dependencies_parsed_at":"2022-11-01T23:34:10.671Z","dependency_job_id":null,"html_url":"https://github.com/unboxme/PureForm","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/unboxme/PureForm","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unboxme%2FPureForm","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unboxme%2FPureForm/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unboxme%2FPureForm/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unboxme%2FPureForm/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/unboxme","download_url":"https://codeload.github.com/unboxme/PureForm/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/unboxme%2FPureForm/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280622572,"owners_count":26362261,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-23T02:00:06.710Z","response_time":142,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["forms","json","prototype","storyboard","tableview","validation","xcode"],"created_at":"2025-10-23T12:56:04.609Z","updated_at":"2025-10-23T12:56:07.677Z","avatar_url":"https://github.com/unboxme.png","language":"Objective-C","funding_links":[],"categories":[],"sub_categories":[],"readme":"PureForm — the easiest way to build form such as login, questionnaire and etc. screens from JSON file. PureForm provides parsing properties and special params into objects for further manipulation of them. \n\n## Setup\n\n### Manually\n\nDownload the source files from the [PureForm subdirectory](https://github.com/unboxme/PureForm/tree/master/PureForm). Then just add source files to your Xcode project and import the `PureLayout.h` header.\n\n### Cocoapods\n\nAdd the pod PureForm to your Podfile:\n\n```ruby\nplatform :ios, '8.0'\n\ntarget 'YourProject' do\n    pod 'PureForm'\nend\n```\n\nThen, run the following command:\n\n```terminal\n$ pod install\n```\n\n## Usage\n\nPureForm is clean and pretty easy to use in several steps:\n\n1. Describe your form in a JSON file using `JSON Rules` paragraph below;\n2. Create settings via `PFSettings` using `Settings` paragraph below:\n\n    ```objc\n    PFSettings *settings = [[PFSettings alloc] init];\n    settings.keyboardTypeValidation = YES;\n    settings.keyboardAvoiding = YES;\n    settings.formDelegate = self;\n    settings.tableViewDelegate = self;\n\n    // etc.\n    ```\n3. Create a `PFFormController` instance with a `UITableView` and settings which were created at the previous step:\n\n    ```objc\n    self.formController = [[PFFormController alloc] initWithTableView:self.tableView settings:settings];\n    ```\n4. Just use a `makeFormWithJSONFile:` method to create and display your form from the JSON file from the first step:\n\n    ```objc\n    [self.formController makeFormWithJSONFile:@\"form\"];\n    ```\n\n5. That's it!\n\n## Settings\n\nThe [settings header](PureForm/Models/PFSettings.h) is fully documented. There are main params here you can set:\n\n* `keyboardTypeValidation`\n* `keyboardAvoiding`\n* `failureReasons`\n* `cellHeight`\n\nAs well as delegates for `UIKit` controls:\n\n* `PFFormDelegate`\n* `UITableViewDelegate`\n* `UITextFieldDelegate`\n* `PFSegmentedControlDelegate`\n* `PFSwitchControlDelegate`\n* `PFSliderControlDelegate`\n* `PFStepperControlDelegate`\n\n## JSON Rules\n\nDescribe your custom cell in JSON just using property names and values for them. Of course, __reserved words__ and __special chars__ are used too. You can find reserved words and special chars in a [constants header](PureForm/Common/PFConstants.h).\n\n### Basics\n\n* Pairs of class cell name or cell identifier and reserved words are segregated by `\u003c` and `\u003e`. \n* The base structure for 2 cells looks like __(pay attention on levels)__:\n\n ```\n[\t\t\t\t\t\t\t\t\t   \t\t    /// 0 level\n  {\n    \"\u003ccell_class_name + cell_identifier\u003e\": {   // First cell\n      property_name_1: {\t\t\t\t\t   /// 1 level\n        in_property_name_1.1: value,\t\t   /// 2 level\n        in_property_name_1.2: value\n      },\n      property_name_2: {\n        in_property_name_2.1: value\n      }\n    }\n  },\n  {\n    \"\u003ccell_class_name + cell_identifier\u003e\": { \t// Second cell\n    // Setup\n  },\n  {\n  // etc.\n  }\n]\n```\n__Note that JSON parsing supports only 2 levels of nesting yet.__\n* If a cell class name or a cell identifier equals to the previous one, you can simplify it using `=` like that:\n\n ```\n {\n    \"\u003c= + =\u003e\": { \t\t\t\t\t\t\t\t\t// Any cell\n    // Setup\n },\n```\n* Usage of reserved words and special chars:\n\n | Reserved word | Level | Value \n|----------------------|---------|----------\n| `\u003csection\u003e`\t | 0 | index of section \n| `\u003cvalue\u003e`        | 1 | current value\n| `\u003ckey\u003e`           | 1 | save key for output dictionary\n| `\u003cvalidators\u003e` | 1 | array of validators\n| `\u003cdisplay\u003e` \t | 1 | property name to display value after change\n__All reserved words and special chars are optional.__\n\n | Char | Usage in | Example | Description\n |------------------|-----------|-------------|------\n | ? | property name | textField? | Shows that it's a form for validation — not just a view\n | ! | validator name | min_value! | Starts validation immediately after value change\n | * | property name | text* | Shows that this value is a key for `NSLocalizedString` macros\n | # | value | ic_turtle#6F3F83 or #6F3F83| Uses as it is or for hex coloring image by their name\n* Available validator keys for `\u003cvalidators\u003e`:\n\n | Validator | Value\n|-------------|----------\n| `equal` | string or number\n| `equal_next` | `true`\n| `equal_previous` | `true`\n| `equal_length` | number\n| `min_length` | number\n| `max_length` | number\n| `min_value` | number\n| `max_value` | number\n| `required` | `true`\n| `type` | `email` or `full_name`\n| `custom` | regex string\n__Validators are used in 2 level and they should be nested into `\u003cvalidators\u003e`.__\n  \n* Enums are just numeric values in JSON. By the way there are some enums which are associated with string values:\n\t* `UIKeyboardType`\n\t* `UITextAutocapitalizationType`\n\t* `UITextAutocorrectionType`\n\t* `UITextSpellCheckingType`\n\t* `UIKeyboardAppearance`\n\t* `UIReturnKeyType`\n\t* `UITextFieldViewMode`\n\n### Examples\n\n* Well, how it looks in a real example: \n\n ```json\n[\n  {\n    \"\u003cTextFieldCell + TextFieldCellIdentifier\u003e\": {\n      \"textField?\": {\n        \"placeholder\": \"Huh, centered?\",\n        \"textAlignment\": 1\n      }\n    }\n  }\n]\n```\n\n\u003cp align='center'\u003e\n\t\u003cimg height='600' src='https://github.com/unboxme/PureForm/blob/master/Screenshots/centered_text.png'\u003e\n\u003c/p\u003e\n\n* Now let's make a login form with validators:\n\n ```json\n[\n  {\n    \"\u003cTextFieldCell + TextFieldCellIdentifier\u003e\": {\n      \"textField?\": {\n        \"placeholder\": \"Login\",\n        \"textAlignment\": 1,\n        \"keyboardType\": \"UIKeyboardTypeEmailAddress\",\n        \"\u003ckey\u003e\": \"login\",\n        \"\u003cvalidators\u003e\": {\n          \"type\": \"email\"\n        }\n      }\n    }\n  },\n  {\n    \"\u003c= + =\u003e\": {\n      \"textField?\": {\n        \"placeholder\": \"Password\",\n        \"textAlignment\": 1,\n        \"secureTextEntry\": true,\n        \"\u003ckey\u003e\": \"password\",\n        \"\u003cvalidators\u003e\": {\n          \"min_length!\": 6,\n          \"max_length!\": 25\n        }\n      }\n    }\n  },\n  {\n  \"\u003csection\u003e\": 1\n  },\n  {\n    \"\u003cButtonCell + ButtonCellIdentifier\u003e\": {\n      \"titleLabel\": {\n        \"text\": \"Login\",\n        \"textColor\": \"#6F3F83\"\n      }\n    }\n  }\n]\n```\n\n\u003cp align='center'\u003e\n\t\u003cimg height='600' src='https://github.com/unboxme/PureForm/blob/master/Screenshots/clean_form.png'\u003e\n\u003c/p\u003e\n\n* It remains only to validate entered values and save they into the dictionary. Credentials from left form satisfies the validators and `[self.formController validate]` will return `YES`:\n\n ```objc\nif ([self.formController validate]) {\n\tNSDictionary *loginInfo = [self.formController allKeyValuePairs];\n\t// Send it to server\n}\n ```\n \n \u003cp align='center'\u003e\n\t\u003cimg height='600' src='https://github.com/unboxme/PureForm/blob/master/Screenshots/filled_form.png'\u003e\n\t\u003cimg height='600' src='https://github.com/unboxme/PureForm/blob/master/Screenshots/filled_form_error.png'\u003e\n\u003c/p\u003e\n\n## Notes\n\n* Example project files will open properly only in Xcode 8.\n\n## TODO\n\n- [ ] Remove limit of nesting\n- [x] Keyboard avoiding (issue #2)\n- [ ] Targets for buttons\n- [ ] Support of UITextView\n- [ ] Wrapper for editing common properties \n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funboxme%2Fpureform","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Funboxme%2Fpureform","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Funboxme%2Fpureform/lists"}