In a language like JavaScript, configuration objects (or, as they’re known by JS convention, options), are just a dictionary. Default options are merged into the dictionary using a function like Underscore.js’s _.defaults.

Because of Swift’s type system, typeless dictionaries aren’t as nice to use as they are in a more dynamic language like JavaScript. Structs, on the other hand, make for great configuration objects. Unfortunately, configuring those configuration objects is sometimes a bit unweildy. Let’s take a look at the data for a form’s text field.

struct FieldData {
	let title: String
	let placeholder: String
	let keyboardType: UIKeyboardType
	let secureEntry: Bool
	let autocorrectType: UITextAutocorrectionType
	let autocapitalizationType: UITextAutocapitalizationType
}

This struct will give us an implicit “memberwise” initializer, but let’s write it explicitly.

init(title: String, placeholder: String, keyboardType: UIKeyboardType, secureEntry: Bool, autocorrectType: UITextAutocorrectionType, autocapitalizationType: UITextAutocapitalizationType) {
	self.title = title
	self.placeholder = placeholder
	self.keyboardType = keyboardType
	self.secureEntry = secureEntry
	self.autocorrectType = autocorrectType
	self.autocapitalizationType = autocapitalizationType
}

To use this particular initializer, you’ll have to pass in all the defaults yourself. To rectify that, we can make a different intializer that has defaults built in, by using the default parameter syntax. It’s getting really unwieldy, so let’s break it onto multiple lines as well.

init(title: String,
	placeholder: String = "",
	keyboardType: UIKeyboardType = .Default,
	secureEntry: Bool = false,
	autocorrectType: UITextAutocorrectionType = .None,
	autocapitalizationType: UITextAutocapitalizationType = .None)
	{
		self.title = title
		self.placeholder = placeholder
		self.keyboardType = keyboardType
		self.secureEntry = secureEntry
		self.autocorrectType = autocorrectType
		self.autocapitalizationType = autocapitalizationType
}

This initializer is mostly pretty good. Because of all of the default values, you can use this intializer with just a title, like so:

let fieldData = FieldData(title: "First Name")

You can also use it with any of the defaults overridden, like so:

let fieldData = FieldData(title: "First Name", secureEntry: true)

Even though secureEntry is the fourth parameter, any parameters with defaults can be skipped. Swift does the right thing here, and that’s awesome. We could leave this as-is, but I wanted to go a step further. I don’t like how big the initializer is. Each property of the struct is declared in 3 places: first, in the property declaration; second, in the initializer’s function declaration, and lastly in the setter in the body of the declaration. This might not seem like a big deal, but every time you add, remove, or change a property, you’ll have to touch three pieces of code.

I toyed around with a few ways to fix this issue, including making the instance variables optional and filling in the defaults at the usage site, but that ended up being just as clunky as the big initializer. What I settled on was: instead of making the variables optional, I made them mutable. That solves quite a few problems. Let’s take a look:

struct FieldData {
	let title: String
	var placeholder = ""
	var keyboardType = UIKeyboardType.Default
	var secureEntry = false
	var autocorrectType = UITextAutocorrectionType.No
	var autocapitalizationType = UITextAutocapitalizationType.None
	
	init(title: String) {
		self.title = title
	}
}

Our initializer is now dead simple. It has only the required parameters in it. Everything else has an easy to read default in the property declaration. We could add more spacing or documentation to those properties, as needed.

Next, I used a great little microlibrary called Then, which helps clean up initialization of objects. It’s a dependency, but it has a really simple definition:

public protocol Then {}

extension Then {
    public func then(@noescape block: inout Self -> Void) -> Self {
        var copy = self
        block(&copy)
        return copy
    }
}

That’s it. From this, we can extend our FieldData struct with Then:

extension FieldData: Then { }

And go to town:

let fieldData = FieldData(title: "Password").then({
	$0.secureEntry = true
})

While this solution does have mutable properties, I think the wins in the readability of the call site and changeability of the code are worth it.

Using then for view configuration

The then extension is a really useful library to have in your app. By default, it extends all NSObject types:

extension NSObject: Then { }

Since everything in Cocoa Touch inherits from NSObject, you can now use this function to configure lots of types, and you can do so at the declaration of the property. Swift will let you initialize things in-line (as long as they’re effectively a one line expression):

let footerContainer = UIView().then({
    $0.backgroundColor = UIColor.grayColor()
})

Since then returns self, you can also chain calls to then. By moving common view configuration into a free function, like so:

struct Style
	static func whiteButton(inout button: UIButton) {
		button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
		button.contentVerticalAlignment = .Center
		
		button.setBackgroundColor(UIColor.whiteColor(), forState: .Normal)
		button.setBackgroundColor(UIColor.lightGrayColor, forState: .Hightlighted)
	}
}

Because this function has the same form as the function that then expects, you can pass it straight to then, and call then a second time to do more customized configuration:

let button = UIButton().then(Style.whiteButton).then({
	$0.setTitle("Continue", forState: .Normal)
})

Go grab the then function. It’s super useful.