Former is a fully customizable Swift library for easy creating UITableView based form.

Related tags

Form Former


Former is a fully customizable Swift library for easy creating UITableView based form.

Swift CocoaPods Shield Carthage compatible MIT License

Submitting Issues

Click HERE 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.

Submitting Feature Requests

Click HERE 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.




  • Xcode 10+
  • Swift 4.2+
  • iOS 10.0+

Still wanna use iOS7 and swift 2.2 or 2.3?
-> You can use 1.4.0 instead.



Add the following line to your Podfile:


target 'YOUR_TARGET_NAME' do

  pod 'Former'


Add the following line to your Cartfile:

github "ra1028/Former"


You can set the cell's appearance and events-callback at the same time.
ViewController and Cell do not need to override the provided defaults.

Simple Example

import Former

final class ViewController: FormViewController {

    override func viewDidLoad() {
        let labelRow = LabelRowFormer<FormLabelCell>()
            .configure { row in
                row.text = "Label Cell"
            }.onSelected { row in
                // Do Something
        let inlinePickerRow = InlinePickerRowFormer<FormInlinePickerCell, Int>() {
            $0.titleLabel.text = "Inline Picker Cell"
            }.configure { row in
                row.pickerItems = (1...5).map {
                    InlinePickerItem(title: "Option\($0)", value: Int($0))
            }.onValueChanged { item in
                // Do Something
        let header = LabelViewFormer<FormLabelHeaderView>() { view in
            view.titleLabel.text = "Label Header"
        let section = SectionFormer(rowFormer: labelRow, inlinePickerRow)
            .set(headerViewFormer: header)
        former.append(sectionFormer: section)


RowFormer is the base class of the class that manages the cell. A cell that is managed by the RowFormer class should conform to the corresponding protocol. Each of the RowFormer classes exposes event handling in functions named "on*" (e.g., onSelected, onValueChanged, etc...)
Default provided RowFormer classes and the protocols that corresponding to it are listed below.

Demo Class Protocol Default provided cell
Free CustomRowFormer None None
LabelRowFormer LabelFormableRow FormLabelCell
TextFieldRowFormer TextFieldFormableRow FormTextFieldCell
TextViewRowFormer TextViewFormableRow FormTextViewCell
CheckRowFormer CheckFormableRow FormCheckCell
SwitchRowFormer SwitchFormableRow FormSwitchCell
StepperRowFormer StepperFormableRow FormStepperCell
SegmentedRowFormer SegmentedFormableRow FormSegmentedCell
SliderRowFormer SliderFormableRow FormSliderCell
PickerRowFormer PickerFormableRow FormPickerCell
DatePickerRowFormer DatePickerFormableRow FormDatePickerCell
SelectorPickerRowFormer SelectorPickerFormableRow FormSelectorPickerCell
SelectorDatePickerRowFormer SelectorDatePickerFormableRow FormSelectorDatePickerCell
InlinePickerRowFormer InlinePickerFormableRow FormInlinePickerCell
InlineDatePickerRowFormer InlineDatePickerFormableRow FormInlineDatePickerCell

example with LabelRowFormer

let labelRow = LabelRowFormer<YourLabelCell>(instantiateType: .Nib(nibName: "YourLabelCell")) {
    $0.titleLabel.textColor = .blackColor()
    }.configure { row in
        row.rowHeight = 44
        row.text = "Label Cell"
    }.onSelected { row in
        print("\(row.text) Selected !!")

update the cell

row.update { row in
    row.text = "Updated title"
row.cellUpdate { cell in
    cell.titleLabel.textColor = .redColor()

get cell instance

let cell = row.cell

set dynamic row height

row.dynamicRowHeight { tableView, indexPath -> CGFloat in
    return 100


ViewFormer is base class of the class that manages the HeaderFooterView.
A HeaderFooterView that is managed by the ViewFormer class should conform to the corresponding protocol. Default provided ViewFormer classes and the protocols that correspond to it are listed below.

Demo Class Protocol Default provided cell
Free CustomViewFormer None None
LabelViewFormer LabelFormableView FormLabelHeaderView FormLabelFooterView

example with LabelViewFormer

let headerView = LabelViewFormer<YourLabelView>(instantiateType: .Nib(nibName: "YourLabelView")) {
    $0.titleLabel.textColor = .blackColor()
    }.configure { view in
        view.viewHeight = 30
        view.text = "Label HeaderFooter View"


SectionFormer is a class that represents the Section of TableView.
SectionFormer can append, add, insert, remove the RowFormer and set the ViewFormer.

let section = SectionFormer(rowFormer: row1, row2, row3)
    .set(headerViewFormer: headerView)
    .set(footerViewFormer: footerView)

add the cell

section.append(rowFormer: row1, row2, row3)
section.add(rowFormers: rows)
section.insert(rowFormer: row, toIndex: 3)
section.insert(rowFormer: row, below: otherRow)
// etc...

remove the cell

section.remove(rowFormer: row)
// etc...

set the HeaderFooterViewe

section.set(headerViewFormer: headerView)
section.set(footerViewFormer: footerView)


Former is a class that manages the entire form.
Examples is below.
add the section or cell

former.append(sectionFormer: row)
former.add(sectionFormers: rows)
former.insert(sectionFormer: section, toSection: 0)
former.insert(rowFormer: row, toIndexPath: indexPath)
former.insert(sectionFormer: section, above: otherSection)
former.insert(rowFormers: row, below: otherRow)
// etc...

// with animation
former.insertUpdate(sectionFormer: section, toSection: 0, rowAnimation: .Automatic)
former.insertUpdate(rowFormer: row, toIndexPath: indexPath, rowAnimation: .Left)
former.insertUpdate(sectionFormer: section, below: otherSection, rowAnimation: .Fade)
former.insertUpdate(rowFormers: rows, above: otherRow, rowAnimation: .Bottom)
// etc...

remove the section or cell

former.remove(rowFormer: row1, row2)
former.remove(sectionFormer: section1, section2)
// etc...

// with animation
former.removeUpdate(sectionFormers: sections, rowAnimation: .Middle)
// etc...

Select and deselect the cell indexPath, animated: true, scrollPosition: .Middle) row, animated: true)
// etc...

end editing


become editing next/previous cell

if former.canBecomeEditingNext() {
if former.canBecomeEditingPrevious() {

functions to setting event handling

public func onCellSelected(handler: (NSIndexPath -> Void)) -> Self
public func onScroll(handler: ((scrollView: UIScrollView) -> Void)) -> Self    
public func onBeginDragging(handler: (UIScrollView -> Void)) -> Self
public func willDeselectCell(handler: (NSIndexPath -> NSIndexPath?)) -> Self
public func willDisplayCell(handler: (NSIndexPath -> Void)) -> Self
public func willDisplayHeader(handler: (/*section:*/Int -> Void)) -> Self
public func willDisplayFooter(handler: (/*section:*/Int -> Void)) -> Self        
public func didDeselectCell(handler: (NSIndexPath -> Void)) -> Self
public func didEndDisplayingCell(handler: (NSIndexPath -> Void)) -> Self
public func didEndDisplayingHeader(handler: (/*section:*/Int -> Void)) -> Self
public func didEndDisplayingFooter(handler: (/*section:*/Int -> Void)) -> Self
public func didHighlightCell(handler: (NSIndexPath -> Void)) -> Self
public func didUnHighlightCell(handler: (NSIndexPath -> Void)) -> Self


There is no need to inherit from the FormViewController class.
Instead, create an instance of UITableView and Former, as in the following example.

final class YourViewController: UIViewController {    

    private let tableView: UITableView = UITableView(frame:, style: .Grouped) // It may be IBOutlet. Not forget to addSubview.
    private lazy var former: Former = Former(tableView: self.tableView)


Cell There is likewise no need to inherit from the default provided cell class (FormLabelCell etc ...); only conform to the corresponding protocol. You can use Nibs, of course. An example with LabelRowFormer:

final class YourCell: UITableViewCell, LabelFormableRow {

    // MARK: LabelFormableRow

    func formTextLabel() -> UILabel? {
        return titleLabel

    func formSubTextLabel() -> UILabel? {
        return subTitleLabel

    func updateWithRowFormer(rowFormer: RowFormer) {
        // Do something

    // MARK: UITableViewCell

    var titleLabel: UILabel?
    var subTitleLabel: UILabel?


RowFormer If you want to create a custom RowFormer, make your class inherit from BaseRowFormer and comply with the Formable protocol.
It must conform to ConfigurableInlineForm. In the case of InlineRowFomer, conform to the UpdatableSelectorForm case of SelectorRowFormer. Please look at the source code for details.
Examples of RowFormer using cells with two UITextFields:

public protocol DoubleTextFieldFormableRow: FormableRow {

    func formTextField1() -> UITextField
    func formTextField2() -> UITextField

public final class DoubleTextFieldRowFormer<T: UITableViewCell where T: DoubleTextFieldFormableRow>
: BaseRowFormer<T>, Formable {

    // MARK: Public

    override public var canBecomeEditing: Bool {
        return enabled

    public var text1: String?
    public var text2: String?

    public required init(instantiateType: Former.InstantiateType = .Class, cellSetup: (T -> Void)? = nil) {
        super.init(instantiateType: instantiateType, cellSetup: cellSetup)

    public final func onText1Changed(handler: (String -> Void)) -> Self {
        onText1Changed = handler
        return self

    public final func onText2Changed(handler: (String -> Void)) -> Self {
        onText2Changed = handler
        return self

    open override func cellInitialized(cell: T) {
        cell.formTextField1().addTarget(self, action: "text1Changed:", forControlEvents: .EditingChanged)
        cell.formTextField2().addTarget(self, action: "text2Changed:", forControlEvents: .EditingChanged)

    open override func update() {

        cell.selectionStyle = .None
        let textField1 = cell.formTextField1()
        let textField2 = cell.formTextField2()
        textField1.text = text1
        textField2.text = text2        

    // MARK: Private

    private final var onText1Changed: (String -> Void)?
    private final var onText2Changed: (String -> Void)?    

    private dynamic func text1Changed(textField: UITextField) {
        if enabled {
            let text = textField.text ?? ""
            self.text1 = text

    private dynamic func text2Changed(textField: UITextField) {
        if enabled {
            let text = textField.text ?? ""
            self.text2 = text


If 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.

If 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.


Former is available under the MIT license. See the LICENSE file for more info.

  • Update InlinePickerRowFormer.swift - system version check

    Update InlinePickerRowFormer.swift - system version check

    When trying to compare current system version against lowest supported "8.0.0" you should use .OrderedDescending instead of .OrderedAscending, because system version must be higher or equal to the specified one.

    opened by yaricom 12
  • SelectorDatePickerRowFormer - make default date an optional instead of NSDate()

    SelectorDatePickerRowFormer - make default date an optional instead of NSDate()

    SelectorDatePickerRowFormer - make date an optional, add support for default text and date in the SelectorDatePickerFormableRow protocol

    I needed a way to add placeholder text for this Template if the date had never been set before, so i've changed to be an optional, and added 2 protocol methods that return 2 things:

    1. An Optional Default date, the demo has been modified to return NSDate() giving it the same functionality as before
    2. A string to fall back to if the default date is not set and is still nil.
    opened by andrewloyola 9
  • Updating header text

    Updating header text

    Can't update section header text. I tried:

    someHeader.text = "New Title".uppercased()


    someHeader.configure { view in
        view.text = "New Title".uppercased()

    also tried:

    someHeader.viewUpdate { view in
        view.text = "New Title".uppercased()
    help wanted feature request 
    opened by Recouse 7
  • New Developer

    New Developer

    I cannot even call myself a developer yet, b/c I'm still brand new... so please forgive me for this.... When I Run Former and even Former Demo, it builds but there's no Simulator or even a Storyboard that I can find... I thought I was going to be able to see examples.

    Thank you!

    opened by GadgetAddict 7
  • InlinePickerRowFormer: how to select a picker item programmatically

    InlinePickerRowFormer: how to select a picker item programmatically

    Hello, I'm using former to allow the user to edit some data that is persisted locally, as such when initializing my view controller I need former rows to display the current values of the object I have a InlinePickerRowFormer that allows the user to choose between multiple possible values, and I have noticed that no matter what I do it will always default to the first item in the picker, even if selectedRow is not 0

    To set the current row I call $0.selectedRow Inside the configure block, but the row still defaults to the first option

    I have tried using update, cellUpdate and even altering the formDisplayLabel() directly but nothing works, I can change the font of the display label but not the actual text.

    I am positively stumped, I have no idea how to fix this... am I missing something?

    opened by HaikuOezu 5
  • Errore while hide/show dateRow

    Errore while hide/show dateRow

    Hi, i have this code that works fine:

    private func switchInfomationSectionDate() { if moreInformationDate == true { former.insertUpdate(rowFormer: allDayRow!, below: moreDate!) former.insertUpdate(rowFormer: locationRow!, below: allDayRow!) former.insertUpdate(rowFormer: selectAddressRow!, below: locationRow!) } else { former.removeUpdate(rowFormers: [allDayRow!,locationRow!,selectAddressRow!],rowAnimation:.Top) eventDetails["date_start"] = "" eventDetails["date_end"] = "" } }

    i i change one rowFormer, for example: selectAddressRow and i put a datePickerRow

    endRow = InlineDatePickerRowFormer<FormInlineDatePickerCell>() { $0.titleLabel.text = "Fine" $0.titleLabel.font = .boldSystemFontOfSize(15) $0.displayLabel.font = .systemFontOfSize(15) .displayTextFromDate(String.mediumDateShortTime) }

    the row is correctly added, but when i call switchInfomationSectionDate again i obtain:

    *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'attempt to delete row 4 from section 2 which only contains 4 rows before the update' *** First throw call stack:

    Only with this type of row, any ideas?

    opened by lucabecchetti 5
  • Change label attributes for FormLabelCell

    Change label attributes for FormLabelCell

    I'm trying to create a Delete button row, by using a FormLabelCell and then setting the textAlignment to be centered and the textColor to be red. However, those changes don't seem to be working. I'm creating my section like this

    let deleteSection = SectionFormer().append(rowFormer: LabelRowFormer<FormLabelCell>()
                    .configure { row in
                        row.text = "Delete"
                        row.cell.textLabel?.textAlignment = .center
                        row.cell.textLabel?.textColor = .red
                    }.onSelected { row in
                        if let indexPath = self.tableView.indexPath(for: row.cell) {
                            self.tableView.deselectRow(at: indexPath, animated: true)
                self.former.append(sectionFormer: deleteSection)

    When I run this, I get a FormLabelCell, but the "Delete" text is still left aligned and black, not red and centered. Any ideas?

    help wanted 
    opened by danmartyn 4
  • inline pickers: setting of selected item not reflected in the picker (iOS 9.3)

    inline pickers: setting of selected item not reflected in the picker (iOS 9.3)

    due to a missing reload of the picker, a setting of a selected item of the picker is not shown.

    In file PickerRowFormer.swift the following line must be added after line let picker = cell.formPickerView():


    opened by frankl98 4
  • Migrate to swift 4

    Migrate to swift 4

    Swift 4 migrations

    • Changes to NSAttributedString
    • Add @objc to dynamic methods
    • Change Int to UILayoutPriority(rawValue: <Int>) for contentHuggingPriority
    opened by nikhilsh 3
  • FormCell init(style: UITableViewCellStyle, reuseIdentifier: String?) not public

    FormCell init(style: UITableViewCellStyle, reuseIdentifier: String?) not public

    In swift 3, if I don't set this method to public, my custom (non xib) cell classes fall over when the rowFormer tries to create them

    The same applies to FormHeaderFooterView

    opened by jennyinf 3
  • Update TextViewRowFormer.swift

    Update TextViewRowFormer.swift

    When trying to compare current system version against lowest supported "8.0.0" you should use .OrderedDescending instead of .OrderedAscending, because system version must be higher or equal to the specified one.

    opened by yaricom 3
  • "Cannot find type 'TextFiefldFormableRow' in scope"

    Have this protocol implemented in a file, and it's worked for months. All of a sudden I started getting this error. Not sure why. Here's the file:

    import UIKit
    import Former
    import PhoneNumberKit
    class PhoneNumberField: UITableViewCell, TextFiefldFormableRow {
        @IBOutlet weak var titleLabel: UILabel!
        @IBOutlet weak var textField: PhoneNumberTextField!
        override func awakeFromNib() {
            titleLabel.textColor = .formerColor()
            textField.textColor = .formerSubColor()
            textField.countryCodePlaceholderColor = Colorify.Marina
            if #available(iOS 11.0, *) {
                        PhoneNumberKit.CountryCodePicker.commonCountryCodes = ["US", "CA", "MX", "AU", "GB", "DE"]
        override func setSelected(_ selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
            // Configure the view for the selected state
        func formTextField() -> UITextField {
            return textField
        func formTitleLabel() -> UILabel? {
            return titleLabel
        func updateWithRowFormer(_ rowFormer: RowFormer) {}
    opened by jderbs 0
  • Auto-resize height of headers and footers

    Auto-resize height of headers and footers

    Is your feature request related to a problem? Please describe. It's annoying to always have to manually set the viewHeight of a header or footer view as we don't already want a static value, depending of the content and screen size.

    Describe the solution you'd like A simple boolean value to enable autoresizing height of headers and footers, based on the content (for example the whole text of the label becomes visible without setting a static height value).

    opened by marcheimendinger 0
  • `FormSelectorPickerCell` and `FormSelectorDatePickerCell` don't trigger `UIPickerView` appearance

    `FormSelectorPickerCell` and `FormSelectorDatePickerCell` don't trigger `UIPickerView` appearance

    Describe the bug iOS 14+: When using FormSelectorPickerCell or FormSelectorDatePickerCell with internal configurable UIPickerView inside them, tap on the cell doesn't trigger appearance of internal UIPickerView

    To Reproduce Create FormSelectorPickerCell or FormSelectorDatePickerCell and try to tap on them

    Expected behavior UIPickerView appears

    Desktop (please complete the following information):

    • OS: iOS 14.3
    • Version: 1.8.1

    Smartphone (please complete the following information):

    • Device: any device with iOS 14.0 and higher
    opened by dariy-kordiyak 0
  • iOS 14 DatePicker

    iOS 14 DatePicker

    In iOS 14, the DatePicker has been updated. And now when you click on the InlineDatePickerRowFormer, you should immediately open the date picker popup, but not increase the cell height as it works now


    opened by moremi 0
Ryo Aoyama
░░░░░░░░░░░░░░░░░░░░░ ░░░░░░░▀▄░░░▄▀░░░░░░░ ░░░░░▄█▀███▀█▄░░░░░ ░░░█▀███████▀█░░░ ░░░█░█▀▀▀▀▀▀▀█░█░░░ ░░░░░░░▀▀░░░▀▀░░░░░░░ ░░░░░░░░░░░░░░░░░░░░░
Ryo Aoyama
Carbon🚴 A declarative library for building component-based user interfaces in UITableView and UICollectionView.

A declarative library for building component-based user interfaces in UITableView and UICollectionView. Declarative Component-Based Non-Destructive Pr

Ryo Aoyama 1.2k Jan 5, 2023
ObjectForm - a simple yet powerful library to build form for your class models.

ObjectForm A simple yet powerful library to build form for your class models. Motivations I found most form libraries for swift are too complicated to

jakehao 175 Nov 2, 2022
Elegant iOS form builder in Swift

Made with ❤️ by XMARTLABS. This is the re-creation of XLForm in Swift. 简体中文 Overview Contents Requirements Usage How to create a Form Getting row valu

xmartlabs 11.6k Jan 1, 2023
Some cells to Form a Pod

CellsGao Example To run the example project, clone the repo, and run pod install from the Example directory first. Requirements Installation CellsGao

null 0 Nov 2, 2021
The most flexible and powerful way to build a form on iOS

The most flexible and powerful way to build a form on iOS. Form came out from our need to have a form that could share logic between our iOS apps and

HyperRedink 32 Aug 15, 2022
Declarative form building framework for iOS

Formalist Swift framework for building forms on iOS Formalist is a Swift framework for building forms on iOS using a simple, declarative, and readable

Seed 159 May 25, 2022
iOS validation framework with form validation support

ATGValidator ATGValidator is a validation framework written to address most common issues faced while verifying user input data. You can use it to val

null 51 Oct 19, 2022
SherlockForms - An elegant SwiftUI Form builder to create a searchable Settings and DebugMenu screens for iOS

??️‍♂️ SherlockForms What one man can invent Settings UI, another can discover i

Yasuhiro Inami 98 Dec 27, 2022
APValidators - Codeless solution for form validation in iOS!

APValidators is a codeless solution for form validation. Just connect everything right in Interface Builder and you're done. Supports really complex and extendable forms by allowing to connect validators in tree.

Alty 131 Aug 16, 2022
XLForm is the most flexible and powerful iOS library to create dynamic table-view forms. Fully compatible with Swift & Obj-C.

XLForm By XMARTLABS. If you are working in Swift then you should have a look at Eureka, a complete re-design of XLForm in Swift and with more features

xmartlabs 5.8k Jan 6, 2023
SwiftyFORM is a lightweight iOS framework for creating forms

SwiftyFORM is a lightweight iOS framework for creating forms Because form code is hard to write, hard to read, hard to reason about. Has a

Simon Strandgaard 1.1k Dec 29, 2022
A rule-based validation library for Swift

SwiftValidator Swift Validator is a rule-based validation library for Swift. Core Concepts UITextField + [Rule] + (and optional error UILabel) go into

null 1.4k Dec 29, 2022
Meet CRRulerControl - Customizable Control for iOS

Customizable component, created by Cleveroad iOS developers, is aimed at turning a simple ruler into a handy and smart instrument

Cleveroad 112 Oct 2, 2022
SwiftForms is a small and lightweight library written in Swift that allows you to easily create forms.

SwiftForms is a powerful and extremely flexible library written in Swift that allows to create forms by just defining them in a couple of lines. It also provides the ability to customize cells appearance, use custom cells and define your own selector controllers.

Miguel Ángel Ortuño 1.3k Dec 27, 2022
iOS Validation Library

Honour Validation library for iOS inspired by Respect/Validation. Validator.mustBe(Uppercase()).andMust(StartsWith("F")).validate("FOOBAR") ❗ If you w

Jean Pimentel 55 Jun 3, 2021
Declarative data validation framework, written in Swift

Peppermint Introduction Requirements Installation Swift Package Manager Usage Examples Predicates Constraints Predicate Constraint Compound Constraint

iOS NSAgora 43 Nov 22, 2022
Custom-TopBarController - A Custom TopBar Controller With Swift

TopBarController Верстка Для IPhone и IPod вертска адаптивная, для IPad frane To

Fadeev Sergey 1 Aug 2, 2022
GrouponHeader - iOS TableView Header Animation, Swift/UIKit

GrouponHeader Description: iOS TableView Header Animation Technology: Swift, UIK

James Sedlacek 8 Dec 15, 2022
AtomicReferenceCell - Atomic Reference Cell (Arc) for Swift

Atomic Reference Cell This project provide two structures: Arc<T> and WeakArc<T>

cjw 0 Jan 30, 2022