Class Only Protocols In Swift 4

The delegation pattern is common in many of Apple’s Cocoa API’s. When using it with Swift you create a class-only protocol that the delegate adopts. What I had not noticed was a subtle change in the way you declare a class-only protocol in Swift 4.

Class-Only Protocols

If you want a recap on using the delegate pattern see Quick Guide to Swift Delegates. Since Swift 4 the preferred way to declare a class-only protocol is to use AnyObject rather than class. So instead of writing this:

protocol DetailViewControllerDelegate: class {
  func didFinishTask(sender: DetailViewController)

You write this:

protocol DetailViewControllerDelegate: AnyObject {
  func didFinishTask(sender: DetailViewController)

The effect is the same. The delegate that adopts the protocol must be a class.

class MasterViewController: UIViewController {
  weak var delegate: DetailViewControllerDelegate?

extension MasterViewController: DetailViewControllerDelegate {
  func didFinishTask(sender: DetailViewController) { ... }

The compiler catches attempts to use a value type like a struct as the delegate:

// Error
struct MyDelegate: DetailViewControllerDelegate { ... }

Non-class type ‘MyDelegate’ cannot conform to class protocol ‘DetailViewControllerDelegate’

What Changed?

The Swift Programming Language guide has this say on Class-Only Protocols:

You can limit protocol adoption to class types (and not structures or enumerations) by adding the AnyObject protocol to a protocol’s inheritance list.

My thanks to @mmendoza27 for pointing this out to me. The Swift Evolution proposal SE-0156 - Class and Subytpe existentials covers the change:

This proposal merges the concepts of class and AnyObject, which now have the same meaning: they represent an existential for classes.

Prior to Swift 4 there were some subtle differences between using class and AnyObject but that is no longer the case. I don’t know if AnyObject makes the intent any clearer than class but the result is the same:

The protocol can only be adopted by a class (reference semantics). It cannot be adopted by a struct or enum (value semantics).

What Should I Do

Get into the habit of using AnyObject when creating class-only protocols. Using class is not yet deprecated but I assume it will be in a future version of Swift.

Further Reading

Never Miss A Post

Sign up to get my iOS posts and news direct to your inbox and I'll also send you my free iOS Size Classes Cheat Sheet

    Unsubscribe at any time. See Privacy Policy.

    Archives Categories