Skip to content
iOS framework for creating forms
Branch: master
Clone or download
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Documentation Added a "Hire Simon Strandgaard" button to the Readme Feb 11, 2019
Example.xcodeproj
Example Incremented copyright year from 2017 to 2018 Sep 21, 2018
Source Incremented copyright year from 2017 to 2018 Sep 21, 2018
SwiftyFORM.xcodeproj
SwiftyFORM.xcworkspace Added new Xcode file. Stackoverflow people recommend adding it to the… Sep 21, 2018
Tests Incremented copyright year from 2017 to 2018 Sep 21, 2018
.gitignore
.swift-version
.travis.yml
SwiftyFORM.podspec incremented version from 1.6.0 to 1.7.0 Sep 23, 2018
changelog.md incremented version from 1.6.0 to 1.7.0 Sep 23, 2018
credits.md
license.txt
readme.md
todo.md I have started experiencing crashes when expanding/collapsing Sep 17, 2016

readme.md

SwiftyFORM by Simon Strandgaard
SwiftyFORM


Build Status Version License Platform Carthage compatible

SwiftyFORM is an 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

Development happens in the develop branch.

Requirements

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

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

DatePicker with prev button and next button

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

CocoaPods

CocoaPods is a dependency manager for Cocoa projects.

You can install it with the following command:

$ gem install cocoapods

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

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '9.0'
use_frameworks!

pod 'SwiftyFORM'

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

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

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: neoneye@gmail.com
  • If you want to give me some motivation ;-)
You can’t perform that action at this time.