{"id":2548,"url":"https://github.com/ra1028/Former","last_synced_at":"2025-08-06T16:30:58.197Z","repository":{"id":35447315,"uuid":"39714093","full_name":"ra1028/Former","owner":"ra1028","description":"Former is a fully customizable Swift library for easy creating UITableView based form.","archived":false,"fork":false,"pushed_at":"2021-04-28T20:14:18.000Z","size":875,"stargazers_count":1301,"open_issues_count":21,"forks_count":134,"subscribers_count":34,"default_branch":"master","last_synced_at":"2024-11-30T11:04:22.001Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"Swift","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/ra1028.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-07-26T04:59:05.000Z","updated_at":"2024-10-22T13:14:24.000Z","dependencies_parsed_at":"2022-08-20T20:20:48.821Z","dependency_job_id":null,"html_url":"https://github.com/ra1028/Former","commit_stats":null,"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FFormer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FFormer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FFormer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ra1028%2FFormer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ra1028","download_url":"https://codeload.github.com/ra1028/Former/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228599032,"owners_count":17943268,"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","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":[],"created_at":"2024-01-05T20:16:16.542Z","updated_at":"2024-12-09T16:31:01.801Z","avatar_url":"https://github.com/ra1028.png","language":"Swift","funding_links":[],"categories":["UI","Libs","UI [🔝](#readme)","User Interface"],"sub_categories":["Form \u0026 Settings","UI","Other free courses","Mobile"],"readme":"![Former](https://raw.githubusercontent.com/ra1028/Former/master/Logo.png)\n\n#### Former is a fully customizable Swift library for easy creating UITableView based form.\n[![Swift](https://img.shields.io/badge/Swift-5.0-4BC51D.svg?style=flat)](https://developer.apple.com/swift)\n[![CocoaPods Shield](https://img.shields.io/cocoapods/v/Former.svg)](https://cocoapods.org/pods/Former)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![MIT License](http://img.shields.io/badge/license-MIT-green.svg?style=flat)](https://raw.githubusercontent.com/ra1028/Former/master/LICENSE) \n\n## Submitting Issues\nClick [HERE](https://github.com/ra1028/Former/issues/new?template=bug_report.md) to get started with filing a bug report. Please use this template to ensure that your issue doesn't get closed due to lack of information.\n\n## Submitting Feature Requests\nClick [HERE](https://github.com/ra1028/Former/issues/new?template=feature_request.md) to get started with filing a feature request. Please use this template to ensure that your feature request doesn't get denied due to lack of information. Also please keep in mind that while we desire to make this work as well as possible for everyone we won't be able to accomodate all feature requests due to lack of time or alignment with the direction of the plugin, and you may need to consider contributing even if we agree that a feature would benefit the plugin.\n\n## Demo\n\u003cimg src=\"http://i.imgur.com/1gOwZZN.gif\" width=\"220\"\u003e \u003cimg src=\"http://i.imgur.com/g9yeTtV.gif\" width=\"220\"\u003e \u003cimg src=\"http://i.imgur.com/ouM1SsG.gif\" width=\"220\"\u003e\n\n## Contents\n* [Requirements](#Requirements)\n* [Installation](#installation)\n* [Usage](#usage)\n  + [Simple Example](#simple-example)\n  + [RowFormer](#rowformer)\n  + [ViewFormer](#viewformer)\n  + [SectionFormer](#sectionformer)\n  + [Former](#former)\n  + [Customizability](#customizability)\n* [Contributing](#contributing)\n* [Submitting Issues](#submitting-issues)\n* [Submitting Feature Requests](#submitting-feature-requests)\n* [License](#license)\n\n## Requirements  \n- Xcode 10+\n- Swift 4.2+\n- iOS 10.0+\n\n_Still wanna use iOS7 and swift 2.2 or 2.3?_  \n-\u003e You can use [1.4.0](https://github.com/ra1028/Former/tree/1.4.0) instead.  \n\n## Installation\n#### [CocoaPods](https://cocoapods.org/)\nAdd the following line to your Podfile:\n```ruby\nuse_frameworks!\n\ntarget 'YOUR_TARGET_NAME' do\n\n  pod 'Former'\n  \nend\n```\n#### [Carthage](https://github.com/Carthage/Carthage)\nAdd the following line to your Cartfile:\n```ruby\ngithub \"ra1028/Former\"\n```\n\n## Usage\nYou can set the cell's appearance and events-callback at the same time.  \nViewController and Cell do not need to override the provided defaults. \n\n### Simple Example\n```Swift\nimport Former\n\nfinal class ViewController: FormViewController {\n\n    override func viewDidLoad() {\n        super.viewDidLoad()\n        let labelRow = LabelRowFormer\u003cFormLabelCell\u003e()\n            .configure { row in\n                row.text = \"Label Cell\"\n            }.onSelected { row in\n                // Do Something\n        }\n        let inlinePickerRow = InlinePickerRowFormer\u003cFormInlinePickerCell, Int\u003e() {\n            $0.titleLabel.text = \"Inline Picker Cell\"\n            }.configure { row in\n                row.pickerItems = (1...5).map {\n                    InlinePickerItem(title: \"Option\\($0)\", value: Int($0))\n                }\n            }.onValueChanged { item in\n                // Do Something\n        }\n        let header = LabelViewFormer\u003cFormLabelHeaderView\u003e() { view in\n            view.titleLabel.text = \"Label Header\"\n        }\n        let section = SectionFormer(rowFormer: labelRow, inlinePickerRow)\n            .set(headerViewFormer: header)\n        former.append(sectionFormer: section)\n    }\n}\n```\n\n\n### RowFormer\nRowFormer is the base class of the class that manages the cell.\nA cell that is managed by the RowFormer class should conform to the corresponding protocol.\nEach of the RowFormer classes exposes event handling in functions named \"on*\" (e.g., onSelected, onValueChanged, etc...)  \nDefault provided RowFormer classes and the protocols that corresponding to it are listed below.  \n\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eDemo\u003c/th\u003e\n\u003cth\u003eClass\u003c/th\u003e\n\u003cth\u003eProtocol\u003c/th\u003e\n\u003cth\u003eDefault provided cell\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eFree\u003c/td\u003e\n\u003ctd\u003eCustomRowFormer\u003c/td\u003e\n\u003ctd\u003eNone\u003c/td\u003e\n\u003ctd\u003eNone\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/ZTzZAG3.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eLabelRowFormer\u003c/td\u003e\n\u003ctd\u003eLabelFormableRow\u003c/td\u003e\n\u003ctd\u003eFormLabelCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/sLfvbRz.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eTextFieldRowFormer\u003c/td\u003e\n\u003ctd\u003eTextFieldFormableRow\u003c/td\u003e\n\u003ctd\u003eFormTextFieldCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/Es7JOYk.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eTextViewRowFormer\u003c/td\u003e\n\u003ctd\u003eTextViewFormableRow\u003c/td\u003e\n\u003ctd\u003eFormTextViewCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/FjrTL51.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eCheckRowFormer\u003c/td\u003e\n\u003ctd\u003eCheckFormableRow\u003c/td\u003e\n\u003ctd\u003eFormCheckCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/AfidFhs.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eSwitchRowFormer\u003c/td\u003e\n\u003ctd\u003eSwitchFormableRow\u003c/td\u003e\n\u003ctd\u003eFormSwitchCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/ACeA4uq.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eStepperRowFormer\u003c/td\u003e\n\u003ctd\u003eStepperFormableRow\u003c/td\u003e\n\u003ctd\u003eFormStepperCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/0KAJK6v.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eSegmentedRowFormer\u003c/td\u003e\n\u003ctd\u003eSegmentedFormableRow\u003c/td\u003e\n\u003ctd\u003eFormSegmentedCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/i2ibb0P.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eSliderRowFormer\u003c/td\u003e\n\u003ctd\u003eSliderFormableRow\u003c/td\u003e\n\u003ctd\u003eFormSliderCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/Vkfxf2P.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003ePickerRowFormer\u003c/td\u003e\n\u003ctd\u003ePickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormPickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/MLHG4oP.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eDatePickerRowFormer\u003c/td\u003e\n\u003ctd\u003eDatePickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormDatePickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/jUn8Get.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eSelectorPickerRowFormer\u003c/td\u003e\n\u003ctd\u003eSelectorPickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormSelectorPickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/VfxaKoL.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eSelectorDatePickerRowFormer\u003c/td\u003e\n\u003ctd\u003eSelectorDatePickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormSelectorDatePickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/NHb6SXy.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eInlinePickerRowFormer\u003c/td\u003e\n\u003ctd\u003eInlinePickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormInlinePickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/g0M2U4T.gif\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eInlineDatePickerRowFormer\u003c/td\u003e\n\u003ctd\u003eInlineDatePickerFormableRow\u003c/td\u003e\n\u003ctd\u003eFormInlineDatePickerCell\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n__example with LabelRowFormer__  \n```Swift\nlet labelRow = LabelRowFormer\u003cYourLabelCell\u003e(instantiateType: .Nib(nibName: \"YourLabelCell\")) {\n    $0.titleLabel.textColor = .blackColor()\n    }.configure { row in\n        row.rowHeight = 44\n        row.text = \"Label Cell\"\n    }.onSelected { row in\n        print(\"\\(row.text) Selected !!\")\n}\n```\n__update the cell__\n```Swift\nrow.update()\nrow.update { row in\n    row.text = \"Updated title\"\n}\nrow.cellUpdate { cell in\n    cell.titleLabel.textColor = .redColor()\n}\n```\n__get cell instance__\n```Swift\nlet cell = row.cell\nprint(cell.titleLabel.text)\n```\n__set dynamic row height__\n```Swift\nrow.dynamicRowHeight { tableView, indexPath -\u003e CGFloat in\n    return 100\n}\n```\n\n\n### ViewFormer\nViewFormer is base class of the class that manages the HeaderFooterView.  \nA HeaderFooterView that is managed by the ViewFormer class should conform to the corresponding protocol.\nDefault provided ViewFormer classes and the protocols that correspond to it are listed below.  \n\n\u003ctable\u003e\n\u003cthead\u003e\n\u003ctr\u003e\n\u003cth\u003eDemo\u003c/th\u003e\n\u003cth\u003eClass\u003c/th\u003e\n\u003cth\u003eProtocol\u003c/th\u003e\n\u003cth\u003eDefault provided cell\u003c/th\u003e\n\u003c/tr\u003e\n\u003c/thead\u003e\n\n\u003ctbody\u003e\n\u003ctr\u003e\n\u003ctd\u003eFree\u003c/td\u003e\n\u003ctd\u003eCustomViewFormer\u003c/td\u003e\n\u003ctd\u003eNone\u003c/td\u003e\n\u003ctd\u003eNone\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\u003cimg src=\"http://i.imgur.com/Vmmk0dc.png\" width=\"200\"\u003e\u003c/td\u003e\n\u003ctd\u003eLabelViewFormer\u003c/td\u003e\n\u003ctd\u003eLabelFormableView\u003c/td\u003e\n\u003ctd\u003e\nFormLabelHeaderView  \nFormLabelFooterView\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/tbody\u003e\n\u003c/table\u003e\n\n__example with LabelViewFormer__\n```Swift\nlet headerView = LabelViewFormer\u003cYourLabelView\u003e(instantiateType: .Nib(nibName: \"YourLabelView\")) {\n    $0.titleLabel.textColor = .blackColor()\n    }.configure { view in\n        view.viewHeight = 30\n        view.text = \"Label HeaderFooter View\"\n}\n```\n\n\n### SectionFormer\nSectionFormer is a class that represents the Section of TableView.  \nSectionFormer can append, add, insert, remove the RowFormer and set the ViewFormer.  \n__example__  \n```Swift\nlet section = SectionFormer(rowFormer: row1, row2, row3)\n    .set(headerViewFormer: headerView)\n    .set(footerViewFormer: footerView)\n```\n__add the cell__\n```\nsection.append(rowFormer: row1, row2, row3)\nsection.add(rowFormers: rows)\nsection.insert(rowFormer: row, toIndex: 3)\nsection.insert(rowFormer: row, below: otherRow)\n// etc...\n```\n__remove the cell__\n```Swift\nsection.remove(0)\nsection.remove(0...5)\nsection.remove(rowFormer: row)\n// etc...\n```\n__set the HeaderFooterViewe__\n```Swift\nsection.set(headerViewFormer: headerView)\nsection.set(footerViewFormer: footerView)\n```\n\n\n### Former\nFormer is a class that manages the entire form.  \nExamples is below.  \n__add the section or cell__\n```Swift\nformer.append(sectionFormer: row)\nformer.add(sectionFormers: rows)\nformer.insert(sectionFormer: section, toSection: 0)\nformer.insert(rowFormer: row, toIndexPath: indexPath)\nformer.insert(sectionFormer: section, above: otherSection)\nformer.insert(rowFormers: row, below: otherRow)\n// etc...\n\n// with animation\nformer.insertUpdate(sectionFormer: section, toSection: 0, rowAnimation: .Automatic)\nformer.insertUpdate(rowFormer: row, toIndexPath: indexPath, rowAnimation: .Left)\nformer.insertUpdate(sectionFormer: section, below: otherSection, rowAnimation: .Fade)\nformer.insertUpdate(rowFormers: rows, above: otherRow, rowAnimation: .Bottom)\n// etc...\n```\n__remove the section or cell__\n```Swift\nformer.removeAll()\nformer.remove(rowFormer: row1, row2)\nformer.remove(sectionFormer: section1, section2)\n// etc...\n\n// with animation\nformer.removeAllUpdate(.Fade)\nformer.removeUpdate(sectionFormers: sections, rowAnimation: .Middle)\n// etc...\n```\n__Select and deselect the cell__\n```Swift\nformer.select(indexPath: indexPath, animated: true, scrollPosition: .Middle)\nformer.select(rowFormer: row, animated: true)\nformer.deselect(true)\n// etc...\n```\n__end editing__\n```Swift\nformer.endEditing()\n```\n__become editing next/previous cell__\n```Swift\nif former.canBecomeEditingNext() {\n    former.becomeEditingNext()\n}\nif former.canBecomeEditingPrevious() {\n    former.becomeEditingPrevious()\n}\n```\n__functions to setting event handling__\n```Swift\npublic func onCellSelected(handler: (NSIndexPath -\u003e Void)) -\u003e Self\npublic func onScroll(handler: ((scrollView: UIScrollView) -\u003e Void)) -\u003e Self    \npublic func onBeginDragging(handler: (UIScrollView -\u003e Void)) -\u003e Self\npublic func willDeselectCell(handler: (NSIndexPath -\u003e NSIndexPath?)) -\u003e Self\npublic func willDisplayCell(handler: (NSIndexPath -\u003e Void)) -\u003e Self\npublic func willDisplayHeader(handler: (/*section:*/Int -\u003e Void)) -\u003e Self\npublic func willDisplayFooter(handler: (/*section:*/Int -\u003e Void)) -\u003e Self        \npublic func didDeselectCell(handler: (NSIndexPath -\u003e Void)) -\u003e Self\npublic func didEndDisplayingCell(handler: (NSIndexPath -\u003e Void)) -\u003e Self\npublic func didEndDisplayingHeader(handler: (/*section:*/Int -\u003e Void)) -\u003e Self\npublic func didEndDisplayingFooter(handler: (/*section:*/Int -\u003e Void)) -\u003e Self\npublic func didHighlightCell(handler: (NSIndexPath -\u003e Void)) -\u003e Self\npublic func didUnHighlightCell(handler: (NSIndexPath -\u003e Void)) -\u003e Self\n```\n\n\n### Customizability\n__ViewController__  \nThere is no need to inherit from the FormViewController class.  \nInstead, create an instance of UITableView and Former, as in the following example.\n```Swift\nfinal class YourViewController: UIViewController {    \n\n    private let tableView: UITableView = UITableView(frame: CGRect.zero, style: .Grouped) // It may be IBOutlet. Not forget to addSubview.\n    private lazy var former: Former = Former(tableView: self.tableView)\n\n    ...\n```\n__Cell__\nThere is likewise no need to inherit from the default provided cell class (FormLabelCell etc ...); only conform to the corresponding protocol.\nYou can use Nibs, of course.\nAn example with LabelRowFormer:\n```Swift\nfinal class YourCell: UITableViewCell, LabelFormableRow {\n\n    // MARK: LabelFormableRow\n\n    func formTextLabel() -\u003e UILabel? {\n        return titleLabel\n    }\n\n    func formSubTextLabel() -\u003e UILabel? {\n        return subTitleLabel\n    }\n\n    func updateWithRowFormer(rowFormer: RowFormer) {\n        // Do something\n    }\n\n    // MARK: UITableViewCell\n\n    var titleLabel: UILabel?\n    var subTitleLabel: UILabel?\n\n    ...\n```\n__RowFormer__\nIf you want to create a custom RowFormer, make your class inherit from BaseRowFormer and comply with the Formable protocol.  \nIt must conform to ConfigurableInlineForm. In the case of InlineRowFomer, conform to the UpdatableSelectorForm case of SelectorRowFormer.\nPlease look at the source code for details.  \nExamples of RowFormer using cells with two UITextFields:  \n```Swift\npublic protocol DoubleTextFieldFormableRow: FormableRow {\n\n    func formTextField1() -\u003e UITextField\n    func formTextField2() -\u003e UITextField\n}\n\npublic final class DoubleTextFieldRowFormer\u003cT: UITableViewCell where T: DoubleTextFieldFormableRow\u003e\n: BaseRowFormer\u003cT\u003e, Formable {\n\n    // MARK: Public\n\n    override public var canBecomeEditing: Bool {\n        return enabled\n    }\n\n    public var text1: String?\n    public var text2: String?\n\n    public required init(instantiateType: Former.InstantiateType = .Class, cellSetup: (T -\u003e Void)? = nil) {\n        super.init(instantiateType: instantiateType, cellSetup: cellSetup)\n    }\n\n    public final func onText1Changed(handler: (String -\u003e Void)) -\u003e Self {\n        onText1Changed = handler\n        return self\n    }\n\n    public final func onText2Changed(handler: (String -\u003e Void)) -\u003e Self {\n        onText2Changed = handler\n        return self\n    }\n\n    open override func cellInitialized(cell: T) {\n        super.cellInitialized(cell)\n        cell.formTextField1().addTarget(self, action: \"text1Changed:\", forControlEvents: .EditingChanged)\n        cell.formTextField2().addTarget(self, action: \"text2Changed:\", forControlEvents: .EditingChanged)\n    }\n\n    open override func update() {\n        super.update()\n\n        cell.selectionStyle = .None\n        let textField1 = cell.formTextField1()\n        let textField2 = cell.formTextField2()\n        textField1.text = text1\n        textField2.text = text2        \n    }\n\n    // MARK: Private\n\n    private final var onText1Changed: (String -\u003e Void)?\n    private final var onText2Changed: (String -\u003e Void)?    \n\n    private dynamic func text1Changed(textField: UITextField) {\n        if enabled {\n            let text = textField.text ?? \"\"\n            self.text1 = text\n            onText1Changed?(text)\n        }\n    }\n\n    private dynamic func text2Changed(textField: UITextField) {\n        if enabled {\n            let text = textField.text ?? \"\"\n            self.text2 = text\n            onText2Changed?(text)\n        }\n    }\n}\n```\n\n## Contributing\nIf you're interesting in helping us improve and maintain Former, it is highly encouraged that you fork the repository and submit a pull request with your updates.\n\nIf you do chose to submit a pull request, please make sure to clearly document what changes you have made in the description of the PR. \n\n## License\nFormer is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fra1028%2FFormer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fra1028%2FFormer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fra1028%2FFormer/lists"}