SwiftyFORM
  • March 8, 2024

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

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

 

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:

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

GitHub


View Github

#ios #swift #uipickerview #uitableview #validation
YOU MIGHT ALSO LIKE...
🧭 NavigationKit

NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Using Swift Package Manager, add ...

swiftui-navigation-stack

An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation. NavigationStack Installation ...

Stinsen

Simple, powerful and elegant implementation of the Coordinator pattern in SwiftUI. Stinsen is written using 100% SwiftUI which makes it ...

SwiftUI Router

With SwiftUI Router you can power your SwiftUI app with path-based routing. By utilizing a path-based system, navigation in your app becomes ...

FlowStacks

This package takes SwiftUI's familiar and powerful NavigationStack API and gives it superpowers, allowing you to use the same API not just ...