Swift – Reasons to Use Separate Class Extension for Each Delegate

designextension-methodobject-orientedswift-language

I was working through a Ray Wenderlich tutorial and noticed that the author uses class extensions to hold delegate callbacks rather than having them be handled in the class itself i.e.:

delegate callbacks inside class extension:

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

as opposed to having it be contained within the class:

delegate callbacks inside class:

class LogsViewController : UITableViewController, UIPopoverPresentationControllerDelegate {
    func adaptivePresentationStyleForPresentationController(controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
        ...
    }
}

I found this strange and interesting at the same time. He has a file dedicated just to extensions on the LogsViewController class named "LogsViewControllerExtension.swift" and has a different extension for each delegate protocol: UITableViewDataSource, UISplitViewDelegate, etc i.e.:

multiple class extensions each w/ delegate callbacks inside its own file:

extension LogsViewController: UISplitViewControllerDelegate {
    ... callbacks
}

extension LogsViewController : UIPopoverPresentationControllerDelegate {
    ... callbacks
}

Why?

What advantages are there to doing this? I can see where it might be a little more readable to separate this out but at the same time it is a level of indirection. Are there OO principles that are supportive of or against doing this?

Best Answer

I don't know why you said it adds a level of indirection. Maybe you mean something different by that than the traditional meaning, because there is no extra indirection created by doing this. But why do it?

I do it because it is more modular. All the code that is required by the interface is grouped in a single place (except the actual properties.) If I later choose to make a separate class to implement that protocol (and thus introduce an actual level of indirection,) all I need to do is change the extension into a class of it's own (passing the needed properties in through an init function,) and create a property on the ViewController to instantiate the object into.

I also put any private functions which are only used by the functions of that protocol into the extension. I haven't gone so far as to create a completely separate file for the extension, but doing so makes it clear that those private functions are only for that protocol.

And at any rate, people often complain about fat view controllers and breaking a view controller up this way helps keep it better organized, even if it doesn't actually make the view controller thinner.

Related Topic