Enums and Associated Values

State seems to be a dirty word in programming right now, while having statelessservices seems to be the in thing. However, when programming for UI having state is a wonderful thing. You want to be able to quickly know the current state of a component and to be able to change it easily.

First step is to setup a playground with SnapKit and you can find instructions here: CocoaPods and Playgrounds

pod playgrounds SnapKit

The component we will be creating today is a form input. Some things the input will need is a title, placeholder, input field, and a status message. We’ll get something that looks like this:

This is nice and all but where are the enums and assoicated values? And is this really any better then doing it all yourself? You don’t need all the features of the label and textfield nor would you want to expose that in your code to the other developers. You want to create reusable components with set edit points. So lets modify it a bit and add a few easy to use parameters to edit and leave the rest private.

var title: String? { didSet { titleLabel.text = title }}
var placeholder: String? { didSet { textField.placeholder = placeholder }}
var status: String? { didSet { statusLabel.text = status }}
var value: String? {
    set { textField.text = value }
    get { return textField.text }
}

private let titleLabel = UILabel()
private let textField = UITextField()
private let lineView = UIView()
private let statusLabel = UILabel()

...

formInputView.title = "Title"
formInputView.placeholder = "Placeholder"
formInputView.status = "Status"

Finally, we don’t want to show the status when there’s no error. Instead, we will turn the status text and line red when there’s an error and green when its a success. We can achieve this by adding an enum with an associated value.

enum Status {
    case NoError
    case Error(String)
    case Success(String)
}
var status: Status = .NoError { didSet { stateChanged() }}

private func stateChanged() {
    switch status {
    case .NoError:
        statusLabel.text = nil
        lineView.backgroundColor = UIColor.grayColor()
    case .Error(let error):
        statusLabel.text = error
        statusLabel.textColor = UIColor.redColor()
        lineView.backgroundColor = UIColor.redColor()
    case .Success(let success):
        statusLabel.text = success
        statusLabel.textColor = UIColor.greenColor()
        lineView.backgroundColor = UIColor.greenColor()
    }
}

So now our form input looks nice where there’s no error and it is obvious when there is an error:

Final code: