Latest 0.0.3
License MIT
Platforms ios 10.0
Dependencies Sourcery

CI Status

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


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.


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/ -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


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!")



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.



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

pod 'Actionable'


Connor Neville, [email protected]


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

Latest podspec

    "name": "Actionable",
    "version": "0.0.3",
    "summary": "A cleaner delegation pattern for iOS.",
    "description": "Actionable use code generation to give you the benefits of matching the style of builtin iOS delegate protocols with less boilerplate and tedious maintenance.",
    "homepage": "",
    "license": {
        "type": "MIT",
        "file": "LICENSE"
    "authors": {
        "Connor Neville": "[email protected]"
    "source": {
        "git": "",
        "tag": "0.0.3"
    "platforms": {
        "ios": "10.0"
    "source_files": "Sources/**/*",
    "resources": [
    "dependencies": {
        "Sourcery": []
    "swift_version": "4.2"

Pin It on Pinterest

Share This