Forms in iOS — Part 1

Eric Downey
Swift2Go
Published in
7 min readAug 20, 2018

--

Hello everyone! This is my first medium article so feedback is very much appreciated. Today, we are going to look at using the Object reference in Xcode Storyboards. Since I always love real world use cases, the bulk of this article is going to examine how to implement Forms using these Object references. By the end of this article the goal is to have highly reusable form components that can be configured via Storyboards. This is also just part 1. In this part we are going to build a simple form example and in the second article we will examine a more complex example.

Object References

Alright, so what are Object references in Storyboards? You’ve probably seen the Object reference in the UI Library in Xcode (It’s the little yellow cube show in Figure 1). Back in the olden days of iOS dev this object used to be used for the File’s Owner reference in Nib files. If that doesn’t make any sense, don’t worry about it. We live in much better times now.

Figure 1 — Object Reference from Xcode’s UI Library

Now from what I’ve seen, it’s not used very much today. I know up until recently I never used it. So what can it do? The description in Figure 1.0 kinda says it all. These objects can be used to model anything that inherits from the NSObject class. You can attach N number of these things to view controllers in your storyboard. Then you can override their class from the default NSObject. Which is really cool! I can attach a bunch of dependencies to my view controller through the Storyboard. You then setup IBOutlets on your view controller to create references to these objects and the Storyboard will handle instantiating all of these objects.

Now you might be thinking that’s cool and all but couldn’t I just add those dependencies to my view controller without the outlets... Of course you can. However, the power of using the Storyboards means any dependencies of these objects can be configured through the Storyboard as well. The Storyboard will handle instantiating all of these objects for us and we don’t have to worry about it. The objects can also reference elements on the view through IBOutlets. We will see how this helps us next when we are implementing the forms.

Form Objects in Storyboards

This section is going to walk through building a sample Xcode project for our forms example. Feel free to follow along or if you would like to just read, there is a link to the project on my Github at the end of this article. Let’s start with our simple example. Figure 2 has the storyboard configuration for our form. There are two view controllers, one with a button that navigates to the second view controller all embedded in a navigation controller. This will allow us to create more links later on in part 2.

Figure 2— Storyboard Setup for Simple Form Example

The second view controller contains our form. This form is just three labels and three text fields all embedded in UIStackViews. There is also a submit button at the bottom that will print out the values of the forms.

Okay. Let’s get to coding. First, create a new group called Forms in the Xcode project. Then create two new files called Form.swift and FormControl.swift as shown in Figure 3.

Figure 3 — Form Group Setup

We are going to start with the FormControl.swift file. This file is going to contain the following protocol:

@objc protocol FormControl {
var key: String? { get }
var text: String? { get }
func clear()
}

This protocol will be what represents our field controls on each of our forms. The key is to identify the control, text is the value, and clear is to reset the value. Now, you’ll notice this protocol is defined with the @objc tag. This will be important in our next code block.

class Form: NSObject {    @IBOutlet var controls: [FormControl]?    subscript(_ key: String) -> String? {
return value(for: key)
}
func value(for key: String) -> String? {
return controls?.first(where: { $0.key == key })?.text
}
func clear() {
controls?.forEach { $0.clear() }
}
}

The previous code block contains the actual Form class. There a bit of code here, so let’s go through it.

  1. First is the most important part. The IBOutlet referencing an array of FormControl s. This allows us to configure our form object on the Storyboard to have N number of form controls (Text Fields). This is also why the protocol requires the @objc attribute. If the protocol is going to be referenced within the Storyboard, it must have this attribute.
  2. Second is a subscript method to get values from each control field as follows: form["controlName"]
  3. Third is just a function version of our subscript method.
  4. Fourth is the form clear method.

The next file to create and class to implement is going to be the subclass of UITextField . Let’s put this file in our Forms group in Xcode. Here is the implementation:

@IBDesignable class TextField: UITextField {    @IBInspectable var key: String?
}
extension TextField: FormControl {
func clear() {
text = nil
}
}

In the previous code block I declared the TextField class as @IBDesignable to allow the key property to be configured via the Storyboard. Then the class conforms to the FormControl protocol via an extension (I usually implement all of my protocol conformance through extensions). Since the UITextField class already has an optional text property, we don’t need to declare the text property. Lastly let’s implement the simple form view controller:

final class SimpleFormViewController: UIViewController {    @IBOutlet var form: Form!

@IBAction func submit() {
print("Form Data:",
form["firstName"],
form["lastName"],
form["age"])
}
}

And this is it for the view controller. The IBOutlet references our form and the submit button will just print out the values from our form. Simple right! Alright, maybe not the simplest thing in the world, but from here on out, implementing forms should be easy. Let’s hop back over to our Storyboard to finish the configuration for the simple form.

First, change all the UITextField s to TextField s. Then drag one of the Object references to our view controller. You can see the object added to your view controller in the top bar of the interface as shown in Figure 4.

Figure 4 — Form object reference on the SimpleFormViewController

Then we want to change the class of the object reference to a Form object as shown in Figure 5. Once the object is a Form connect the IBOutlet form property to this object in the Storyboard.

Figure 5 — Form Attributes

Then move over to the Outlets inspector for the Form and connect all the text fields to the controls outlet collection in Figure 6.

Figure 6 — Form references to TextField controls

The last thing to configure is to add the keys to each text field. Make sure each text field is configured with the correct key as follows:

  • firstName
  • lastName
  • age

These keys will be how we extract each value from our form and we actually already handled this in the submit action in our view controller. Add the IBAction reference to the submit button in the Storyboard.

And now everything should be ready to go. Whew! That’s a lot steps, but we made it. Build and run, navigate to the simple form, enter some data, and we should get the following output:

Form Data: Optional("Eric") Optional("Downey") Optional("27")

Not the best output (thanks a lot optionals), but you get the idea. This is awesome because we can now have as many forms as we want and our view controllers don’t need to re-implement any form logic. 👍

Even though this is just the simple example, hopefully you can see the power of this design. If you have a lot of forms in your app, it should be really easy to configure your forms in your Storyboard and extract the data. In the next part to Forms in iOS, we are going to expand this implementation to include form validation. Thank you for reading my first article here on medium. 😁 Any feedback is welcome and much appreciated!

Github

https://github.com/Ericdowney/iOSFormExample/tree/article/part1

Versions

  • Xcode 10 Beta 6
  • iOS 12 Beta 8
  • Swift 4.2

--

--

Eric Downey
Swift2Go

Comics and Code! I'm a software consultant with a passion for iOS & Swift