SwiftyFORM is a lightweight iOS framework for creating forms

Overview

SwiftyFORM by Simon Strandgaard
SwiftyFORM


Build Status Version Platform Swift Package Manager Carthage MIT License

SwiftyFORM is a lightweight iOS framework for creating forms

Dark Mode supported

Because form code is hard to write, hard to read, hard to reason about. Has a slow turn around time. Is painful to maintain.

SwiftyFORM demo on YouTube

Requirements

  • iOS 12+
  • Xcode 12+
  • Swift 5.1+

Features

  • Several form items, such as textfield, buttons, sliders
  • Some form items can expand/collapse, such as datepicker, pickerview
  • You can create your own custom form items
  • Align textfields across multiple rows
  • Form validation rule engine
  • Shows with red text where there are problems with validation
  • Strongly Typed
  • Pure Swift
  • No 3rd party dependencies

USAGE

Tutorial 0 - Static text

import SwiftyFORM
class MyViewController: FormViewController {
    override func populate(_ builder: FormBuilder) {
        builder += StaticTextFormItem().title("Hello").value("World")
    }
}

Tutorial 1 - TextField

import SwiftyFORM
class MyViewController: FormViewController {
    override func populate(_ builder: FormBuilder) {
        builder += TextFieldFormItem().title("Email").placeholder("Please specify").keyboardType(.emailAddress)
    }
}

Tutorial 2 - Open child view controller

import SwiftyFORM
class MyViewController: FormViewController {
    override func populate(_ builder: FormBuilder) {
        builder += ViewControllerFormItem().title("Go to view controller").viewController(FirstViewController.self)
    }
}

Advanced - date picker

Date { var dateComponents = DateComponents() dateComponents.day = days let calendar = Calendar.current guard let resultDate = calendar.date(byAdding: dateComponents, to: date) else { return date } return resultDate } func increment() { datePicker.setValue(offsetDate(datePicker.value, days: 1), animated: true) updateSummary() } func decrement() { datePicker.setValue(offsetDate(datePicker.value, days: -1), animated: true) updateSummary() } } ">
class DatePickerBindingViewController: FormViewController {
    override func populate(_ builder: FormBuilder) {
        builder += datePicker
        builder += incrementButton
        builder += decrementButton
        builder += SectionFormItem()
        builder += summary
        updateSummary()
    }
    
    lazy var datePicker: DatePickerFormItem = {
        let instance = DatePickerFormItem()
        instance.title = "Date"
        instance.datePickerMode = .date
        instance.behavior = .expandedAlways
        instance.valueDidChangeBlock = { [weak self] _ in
            self?.updateSummary()
        }
        return instance
    }()
    
    lazy var incrementButton: ButtonFormItem = {
        let instance = ButtonFormItem()
        instance.title = "Next Day"
        instance.action = { [weak self] in
            self?.increment()
        }
        return instance
    }()
    
    lazy var decrementButton: ButtonFormItem = {
        let instance = ButtonFormItem()
        instance.title = "Previous Day"
        instance.action = { [weak self] in
            self?.decrement()
        }
        return instance
    }()
    
    lazy var summary: StaticTextFormItem = {
        return StaticTextFormItem().title("Date").value("-")
    }()
    
    func updateSummary() {
        summary.value = "\(datePicker.value)"
    }
    
    func offsetDate(_ date: Date, days: Int) -> Date {
        var dateComponents = DateComponents()
        dateComponents.day = days
        let calendar = Calendar.current
        guard let resultDate = calendar.date(byAdding: dateComponents, to: date) else {
            return date
        }
        return resultDate
    }
    
    func increment() {
        datePicker.setValue(offsetDate(datePicker.value, days: 1), animated: true)
        updateSummary()
    }
    
    func decrement() {
        datePicker.setValue(offsetDate(datePicker.value, days: -1), animated: true)
        updateSummary()
    }
}

Advanced - Validation

Change password form

class ChangePasswordViewController: FormViewController {
    override func populate(_ builder: FormBuilder) {
        builder.navigationTitle = "Password"
        builder += SectionHeaderTitleFormItem().title("Your Old Password")
        builder += passwordOld
        builder += SectionHeaderTitleFormItem().title("Your New Password")
        builder += passwordNew
        builder += passwordNewRepeated
        builder.alignLeft([passwordOld, passwordNew, passwordNewRepeated])
    }
    
    lazy var passwordOld: TextFieldFormItem = {
        let instance = TextFieldFormItem()
        instance.title("Old password").password().placeholder("required")
        instance.keyboardType = .numberPad
        instance.autocorrectionType = .no
        instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
        instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
        instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
        return instance
        }()
    
    lazy var passwordNew: TextFieldFormItem = {
        let instance = TextFieldFormItem()
        instance.title("New password").password().placeholder("required")
        instance.keyboardType = .numberPad
        instance.autocorrectionType = .no
        instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
        instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
        instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
        return instance
        }()
    
    lazy var passwordNewRepeated: TextFieldFormItem = {
        let instance = TextFieldFormItem()
        instance.title("Repeat password").password().placeholder("required")
        instance.keyboardType = .numberPad
        instance.autocorrectionType = .no
        instance.validate(CharacterSetSpecification.decimalDigitCharacterSet(), message: "Must be digits")
        instance.submitValidate(CountSpecification.min(4), message: "Length must be minimum 4 digits")
        instance.validate(CountSpecification.max(6), message: "Length must be maximum 6 digits")
        return instance
        }()
}

INSTALLATION

Swift Package Manager

With Swift Package Manager support in the latest Xcode, installation has never been easier.

Open your Xcode project -> File -> Swift Packages -> Add Package Dependency...

Search for SwiftyFORM and specify the version you want. The latest tagged release is usually a good idea.

CocoaPods

To integrate SwiftyFORM into your Xcode project using CocoaPods, specify the following in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
swift_version = '5.0'
platform :ios, '12.0'
use_frameworks!

target 'MyApp' do
    pod 'SwiftyFORM', '~> 1.8'
end

Then, run the following command:

$ pod install

Carthage

Link to demo project that shows a minimal SwiftyFORM app using Carthage.

To integrate SwiftyFORM into your Xcode project using Carthage, specify it in your Cartfile:

1.8 ">
github "neoneye/SwiftyFORM" ~> 1.8

Then, run the following command:

$ carthage update

Finally, add SwiftyFORM.framework (will be built by Carthage under Carthage/Build/iOS/) to your project's Linked Frameworks and Libraries in the General tab, and add a new Run Script Build Phase:

  • Set /bin/bash as the shell
  • write /usr/local/bin/carthage copy-frameworks in the script body
  • add $(SRCROOT)/Carthage/Build/iOS/SwiftyFORM.framework to the input files

Manual

  1. Open up Terminal application and cd into your iOS project directory

  2. ONLY IF your project is not already initialized as a git repository, run

$ git init
  1. Add SwiftyFORM as a submodule by running
$ git submodule add https://github.com/neoneye/SwiftyFORM.git
  1. In the Project Navigator, select your application project and go to "Targets" -> "General"

  2. Open the project folder and drag the SwiftyFORM.xcodeproj file into the "Frameworks, Libraries, and Embedded Content" tab of your application.

  3. Click the + button under the "Frameworks, Libraries, and Embedded Content" section and Add the SwiftyFORM.framework

Communication

  • If you want to contribute, submit a pull request.
  • If you found a bug, have suggestions or need help, please, open an issue.
  • If you need help, write me: [email protected]
Comments
  • Error running on phone

    Error running on phone

    Hi i got the following error when i tried running it on my iPhone 6 Plus... Is there any way to solve this problem? I ran the example app directly to test i get the same error as when i did it with my own app.

    screen shot 2015-07-12 at 4 55 31 pm
    opened by OozoraHaruto 7
  • DatePicker Shows only a value button?

    DatePicker Shows only a value button?

    Hi there,

    my datepickers were working fine, but now it shows like in the screenshot, Only todays or setted value like a button in expanded view, and there are no other options - or date picker?

    Edit: i ve also tried :

    var datePicker: DatePickerFormItem = {
                    let instance = DatePickerFormItem()
                    instance.title = "Date"
                    instance.datePickerMode = .date
                    instance.behavior = .expandedAlways
                    return instance
                }()
            builder+=datePicker
            build = builder
    

    but this is also shows like mine, no date picker, only one date value looks like a button

    Edit: by adding "datePicker.preferredDatePickerStyle = .wheels" like:

    func configure(_ model: DatePickerCellModel) {
    		datePicker.datePickerMode = model.datePickerMode
    		datePicker.minimumDate = model.minimumDate
    		datePicker.maximumDate = model.maximumDate
    		datePicker.minuteInterval = model.minuteInterval
    		datePicker.locale = model.resolvedLocale
    		datePicker.date = model.date
            if #available(iOS 13.4, *) {
                datePicker.preferredDatePickerStyle = .wheels
            } else {
                // Fallback on earlier versions
            }
    	}
    

    shows the picker old style. But now; you can not interract with wheels, it just shows it.

    datepicker

    opened by IOS-Sisa 6
  • ViewControllerFormItem and prepareForSegue

    ViewControllerFormItem and prepareForSegue

    Hi!

    Is there a way to configure a view controller form item with a custom action so that I can perform a segue and prepare my destination view controller (pass state etc.)?

    Thanks

    opened by hatembr 6
  • Update Readme to explain how to get results

    Update Readme to explain how to get results

    Having fun using this package. However, I don't see an explanation of how you get the results of the form after its filled out? Am I missing something?

    opened by justdan0227 5
  • TextViewFormItem and TextFieldFormItem are misaligned

    TextViewFormItem and TextFieldFormItem are misaligned

    At first, thank you for your work on this great library. It works like a charm!

    The only problem I've encountered using version 1.2.0 is, that instances of TextViewFormItem and TextFieldFormItem are shown in full width compared to all other form items, as you can see from the attached screenshot. This problem occurs both on iPad and iPhone.

    img_0017

    The code used to create the form is listed below:

        override func populate(_ builder: FormBuilder) {
            builder.navigationTitle = "Image Properties"
            builder += SectionHeaderTitleFormItem().title("Image Properties")
            builder += pickStatusFormField
            builder += starsFormField
            builder += colorFormField
            builder += titleFormField
            builder += subtitleFormField
    
            // ....
        }
    
        private lazy var titleFormField: TextViewFormItem = {
            let field = TextViewFormItem().title("Title")
            field.value = self.properties.title ?? ""
            return field
        }()
    
        private lazy var subtitleFormField: TextViewFormItem = {
            let field = TextViewFormItem().title("Subtitle")
            field.value = self.properties.subtitle ?? ""
            return field
        }()
    
    opened by pboehm 5
  • Multiple line for StaticTextFormItem

    Multiple line for StaticTextFormItem

    I have StaticTextFormItem which has long, more than 200 characters, value. Is it possible to expand the form item so that the form item can show all value?

    opened by saxograph 4
  • Custom FormItem with custom textfield

    Custom FormItem with custom textfield

    I've set up a custom textfield class, which I would like to implement into a form item, but I can't seem to find where to do this. I've found the CustomFormItem class, however I'm unsure of where to go from here. How do I add the custom textfield to the CustomFormItem?

    This is the custom textfield ` class PostCodeTextField: UITextField, UITextFieldDelegate {

    private var characterLimit: Int?
    
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        delegate = self
        autocapitalizationType = .allCharacters
    }
    
    @IBInspectable var maxLength: Int {
        get {
            guard let length = characterLimit else {
                return Int.max
            }
            return length
        }
        set {
            characterLimit = newValue
        }
    }
    
    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        
        guard string.characters.count > 0 else {
            return true
        }
        
        let currentText = textField.text ?? ""
    
        let prospectiveText = (currentText as NSString).replacingCharacters(in: range, with: string)
    
        return prospectiveText.characters.count <= maxLength
        
    }    
    

    `

    And I've made a custom class inheriting from CustomFormItem

    ` public class PostalCodeFormItem: CustomFormItem {

    } `

    Thank in advance!

    opened by Vincent-dejong 4
  • SwiftyFORM fatal error: init(coder:) has not been implemented

    SwiftyFORM fatal error: init(coder:) has not been implemented

    Hello, I am using SwiftyFORM on my ios 9 application.. I've a trouble when implement FormViewController.. The result was: fatal error: init(coder:) has not been implemented What should i do?

    My code was like this: import UIKit import SwiftyFORM

    class MySwiftyFORMController: FormViewController { required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder) }

    override func loadView() {
        super.loadView()
        form_installSubmitButton()
    }
    
    override func populate(builder: FormBuilder) {
        builder.navigationTitle = "Sign Up"
        builder.toolbarMode = .Simple
        builder.demo_showInfo("SocialNetwork 123\nSign up form")
        builder += SectionHeaderTitleFormItem().title("Details")
        builder += userName
    }
    
    lazy var userName: TextFieldFormItem = {
        let instance = TextFieldFormItem()
        instance.title("User Name").placeholder("required")
        instance.keyboardType = .ASCIICapable
        instance.autocorrectionType = .No
        instance.validate(CharacterSetSpecification.lowercaseLetterCharacterSet(), message: "Must be lowercase letters")
        instance.submitValidate(CountSpecification.min(6), message: "Length must be minimum 6 letters")
        instance.validate(CountSpecification.max(8), message: "Length must be maximum 8 letters")
        return instance
        }()
    

    }

    Need your advice. Cheers!

    opened by adrianha 4
  • Changing background color of a button?

    Changing background color of a button?

    Howdy,

    I can see references to styleIdentifier and styleClass but can't seem to figure out what they do or how to use them... Any tips? I'm primarily looking for a way to customize the background color of a button (e.g. red for close)? Not sure if I should just inherit and make my own customized class or if you have a sanctioned way of doing it.

    Maybe something like...

      lazy var closButton: ButtonFormItem = {
        let instance = ButtonFormItem()
        instance.title("Dismiss")
        instance.backgroundColor = UIColor.redColor()
        instance.action = { [weak self] in
          self?.closeMe()
        }
        return instance
        }()
    

    Thank you!

    opened by tehprofessor 4
  • Add 'simple mode' to PrecisionSliderFormItem

    Add 'simple mode' to PrecisionSliderFormItem

    Allow for PrecisionSliderFormItem to be a viable alternative to a regular UISlider, showing the real values for the markers and prevents zooming in or out (works best with smallish integer values) and fixed an issue where center marker on the slider was opaque.

    opened by bradleymackey 3
  • Label font + color customization + many fixes

    Label font + color customization + many fixes

    Just adds a bit more label customisation to the built in FormItems to prevent the need for jumping out to CustomFormItem all the time (#19). Ideally this would be refactored to allow any property on a given form item to be customized without have all the code duplication, but this personally meets my requirements for now!

    (Also fixed issues with iPhone X layout (#36) and bug where TextViewFormItem would size incorrectly)

    opened by bradleymackey 3
  • Sync is not overwritten

    Sync is not overwritten

    Hey,

    in your StaticTextFormItem and other source code files there is a SyncBlock. When compiling with the latest Xcode and iOS 15 SDKs the error is thrown "sync is not overwritten".

    Do you have a solution for that since your library is not usable anymore.

    Kindest regards!

    typealias SyncBlock = (_ value: String) -> Void var syncCellWithValue: SyncBlock = { (string: String) in SwiftyFormLog("sync is not overridden") }

    opened by simongiesen 2
  • TextView looses focus after first character entry

    TextView looses focus after first character entry

    I've noticed that if you use a TextView, that when you put the cursor in the field and start to type, that after the first character focus is lost. If you click the field again you can then continue typing. It's only on the first character the first time.
    I notice that if you go into the example, and try the textview this happens. What is odd is that if you hit clear at the start then the field works correctly. Its only when it has an initial value in it and you start typing that the focus is lost.

    Thoughts?

    opened by justdan0227 6
  • isDirty flag

    isDirty flag

    Is there a concept of if a form is "dirty" (has been edited) vs just displayed that you can check when someone presses a back key to see if anything has been updated?

    opened by justdan0227 17
  • Ability to set autocorrectionType to

    Ability to set autocorrectionType to "no" on initializer

    Is there a way to add .autocorrectionType to the initializer? I can't find one unless I create it with a lazy variable?

    builder += TextFieldFormItem().title("First Name").placeholder("Enter First Name").keyboardType(.default).autocorrectionType.

    opened by justdan0227 1
Owner
Simon Strandgaard
I develop native iOS/macOS apps.
Simon Strandgaard
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
Former is a fully customizable Swift library for easy creating UITableView based form.

Former is a fully customizable Swift library for easy creating UITableView based form. Submitting Issues Click HERE to get started with filing a bug r

Ryo Aoyama 1.3k Dec 27, 2022
Custom Field component with validation for creating easier form-like UI from interface builder.

#YALField Custom Field component with validation for creating easier form-like UI from interface builder. ##Example Project To run the example project

Yalantis 476 Sep 1, 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
A framework to validate inputs of text fields and text views in a convenient way.

FormValidatorSwift The FormValidatorSwift framework allows you to validate inputs of text fields and text views in a convenient way. It has been devel

ustwo™ 500 Nov 29, 2022
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
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
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
Boring-example - Using boring crate from iOS application

BoringSSL example Using boring crate from iOS application. Checkout git clone gi

Alexei Lozovsky 0 Dec 31, 2021
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
GrouponHeader - iOS TableView Header Animation, Swift/UIKit

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

James Sedlacek 8 Dec 15, 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
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
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
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
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
The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms.

Bitwarden Mobile Application The Bitwarden mobile application is written in C# with Xamarin Android, Xamarin iOS, and Xamarin Forms. Build/Run Require

Bitwarden 4.2k Dec 29, 2022
IAMPopup is a simple class for expressing custom popup in various forms.

IAMPopup Introduction IAMPopup is a simple class for expressing custom popup in various forms. This includes where to display the popup and space to d

Hosung Kang 18 Dec 29, 2022
OONI Probe is free and open source software designed to measure internet censorship and other forms of network interference.

OONI Probe iOS OONI Probe is free and open source software designed to measure internet censorship and other forms of network interference. Click here

Open Observatory of Network Interference (OONI) 59 Nov 2, 2022