- July 26, 2025
- Mins Read
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.
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += StaticTextFormItem().title(“Hello”).value(“World”)
}
}
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += TextFieldFormItem().title(“Email”).placeholder(“Please specify”).keyboardType(.emailAddress)
}
}
import SwiftyFORM
class MyViewController: FormViewController {
override func populate(_ builder: FormBuilder) {
builder += ViewControllerFormItem().title(“Go to view controller”).viewController(FirstViewController.self)
}
}
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()
}
}
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
}()
}
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.
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
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:
/bin/bash
as the shell/usr/local/bin/carthage copy-frameworks
in the script body$(SRCROOT)/Carthage/Build/iOS/SwiftyFORM.framework
to the input filesOpen up Terminal application and cd into your iOS project directory
ONLY IF your project is not already initialized as a git repository, run
$ git init
SwiftyFORM
as a submodule by running
$ git submodule add https://github.com/neoneye/SwiftyFORM.git
In the Project Navigator, select your application project and go to “Targets” -> “General”
Open the project folder and drag the SwiftyFORM.xcodeproj
file into the “Frameworks, Libraries, and Embedded Content” tab of your application.
Click the +
button under the “Frameworks, Libraries, and Embedded Content” section and Add
the SwiftyFORM.framework
NavigationKit is a lightweight library which makes SwiftUI navigation super easy to use. 💻 Installation 📦 Swift Package Manager Using Swift Package Manager, add ...
An alternative SwiftUI NavigationView implementing classic stack-based navigation giving also some more control on animations and programmatic navigation. NavigationStack Installation ...
With SwiftUI Router you can power your SwiftUI app with path-based routing. By utilizing a path-based system, navigation in your app becomes ...
This package takes SwiftUI's familiar and powerful NavigationStack API and gives it superpowers, allowing you to use the same API not just ...