Actionable 0.0.3

Actionable 0.0.3

Maintained by Connor Neville.



  • By
  • Connor Neville

Actionable

CI Status Version License Platform

Actionable makes it easier to adopt iOS conventions around the delegation pattern, with less boilerplate.

About

When you want to relay actions to an object's owner in iOS, it’s common to use the delegate pattern. In builtin classes, this pattern looks like:

protocol UITextFieldDelegate: class {
    
    func textFieldDidBeginEditing(UITextField)
    ...
    func textFieldDidEndEditing(UITextField, reason: UITextField.DidEndEditingReason)
    
}

You’re encouraged to pass the object doing the delegation - in this case, the UITextField, back in the function. This naming convention can get verbose, but it has benefits. You might be delegating multiple UITextFields, and use a switch statement to disambiguate. It also makes clear to the developer that a particular function belongs to UITextFieldDelegate, whereas some func didBeginEditing() is more unclear.

But maintaining this style as you develop can be tedious and carry a lot of boilerplate, especially for larger delegates. Actionable leverages Sourcery code generation to make these delegate protocols easier to write and express.

Usage

First, add the build phase that performs the code generation. Insert it prior to the Compile Sources phase. Specify your input files (-i) and the file where your output will be generated (-o). Make sure the output file is added to your Xcode project.

$PODS_ROOT/Actionable/actionable.sh -i $PROJECT_DIR/ -o $PROJECT_DIR/Generated/Actionable+Generated.swift

Now you're ready to add your delegates. To conform to Actionable, simply declare a delegate and a set of actions:

class TableViewCell: UITableViewCell, Actionable {

    // Conforming to Actionable
    weak var delegate: Delegate?
    enum Action {
        case didTapButton
    }
    
    func doSomething() {
        // notify the delegate that something happened
        notify(.didTapButton)
    }
    
}

And on the other side, conform to the newly generated delegate.

class TableViewController: UITableViewController, TableViewCellDelegate {

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(
            withIdentifier: TableViewCell.reuseID, for: indexPath)
            as! TableViewCell
        // assign the controller as the cell’s delegate
        cell.delegate = self
        return cell
    }

    // TableViewCellDelegate, and this function, were generated for you
    func tableViewCell(_ cell: TableViewCell, didNotify action: TableViewCell.Action) {
        switch action {
        case .didTapButton:
            print("Message received!")
        }
    }

}

Example

To run the example project, clone the repo, and run pod install from the Example directory first. You'll see a sample table view, whose buttons send an event all the way up to AppDelegate via the Actionable pattern.

Requirements

Installation

Actionable is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'Actionable'

Author

Connor Neville, [email protected]

License

Actionable is available under the MIT license. See the LICENSE file for more info.