Behaviour Composition with Storyboard’s

Applications are made up of multiple interactions and behaviours. Often times, our view controllers and views end up bloated because of the shear number of interactions that can occur. Furthermore, this makes testing our behaviours even more complicated since they are tied to our view layers.

If you just want to jump straight into the source, you can find a demo project @ github.com

The Deck

Here’s a deck that better explains the concept. Don’t forget to checkout the code and please share 👍

Generic Delegate’s in Swift

A common pattern in cocoa development is the use of the delegate pattern. Most commonly used as a callback mechanism.

In Swift however sometimes we would like to use this pattern along with a generic implementation of our type. First, lets look at the problem.

The Problem

A typical approach would look like this:

struct Item { }

protocol ItemDelegate: class {
    func didSelect(item: Item)
}

final class ItemController {
    weak var delegate: ItemDelegate?
}

This works great while Item is a concrete type, but what if we wanted to make Item generic?

protocol Item { }
struct MyItem: Item { }

final class ItemController<ItemType: Item> {
    weak var delegate: ItemDelegate?
}

Well we can simply make our delegate generic as well right?

protocol ItemDelegate: class {
    func didSelect<ItemType: Item>(item: ItemType)
}

Well actually this isn’t right. To see the problem lets check out the callsite:

let controller = ItemController<MyItem>()
func didSelect<ItemType>(item: ItemType) where ItemType : Item {
    print("\(item)")
}

Specifically where ItemType : Item. Item is our protocol and not our concrete type MyItem. So even though we’ve successfully constrained our controller to a specific type, our delegate is much less specific.

The Solution

What we really want to do is define an associatedtype on our delegate.

protocol ItemDelegate {
    associatedtype ItemType: Item
    func didSelect(item: ItemType)
}

The problem is that now we have a generic constraint on our ItemDelegate. The solution is actually quite simple. Instead of constraining our ItemController to a specific Item, instead constrain it to a specific ItemDelegate.

Our final solution would look like the following:

protocol ItemDelegate: class {
    associatedtype ItemType: Item
    func didSelect(item: ItemType)
}

final class ItemController<Delegate: ItemDelegate> {
    weak var delegate: Delegate?
    func addItem(item: Delegate.ItemType)
}

Now if we look at our callsite:

let controller = ItemController<MyItem>()
func didSelect(item: MyItem) {
    print("\(item.name)")
}

Recap

By moving the generic constraint to the delegate we can now safely define an instance of ItemController and ensure our delegate callbacks are type-safe to the same concrete instance.

This is a fairly simple approach but makes working with generic delegate’s much simpler and much safer.