Quick Guide to Swift Delegates

Since I got talking about delegation last week here are my quick notes to implementing delegates with Swift compared to Objective-C.

Updated 30 Apr 2018 to use AnyObject. See Class Only Protocols In Swift 4

Key Steps to Delegation

The delegation design pattern has long been a core competency for Cocoa programmers. This remains the case with the arrival of Swift. Regardless of whether you are using Objective-C or Swift the basic steps to use delegation are the same:

  1. Create a delegate protocol that defines the responsibilities of the delegate.
  2. Create a delegate property in the delegating class to keep track of the delegate.
  3. Adopt and implement the delegate methods in the delegate class.
  4. Call the delegate from the delegating object.

Note that there are a couple of differences between Swift and Objective-C support for delegates:

Create the Delegate Protocol

Let’s create a delegate protocol that a view controller might use to tell a parent or master view controller that a task has finished.

In Objective-C:

@protocol DetailViewControllerProtocol <NSObject>
- (void)didFinishTask:(DetailViewController *)sender;
@end

The Swift code is similar:

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

Notes:

Add a Delegate Property

Our delegating class needs a reference to the delegate - but should it be a strong or weak reference? We need to pay attention not to create a retain cycle between the delegate and the delegating objects. That can happen if our delegate already has a strong reference to our delegating object. In that case we should make our delegate a weak reference. In Objective-C we do that as follows:

@property (weak) id<DetailViewControllerProtocol>delegate;

Since we do not always set a delegate we use an optional property in Swift:

weak var delegate:DetailViewControllerDelegate?

Notes:

Adopt and implement the Delegate Protocol

In our delegate class we tell the compiler that we are adopting the protocol and then implement the delegate method(s). In Objective-C we can use a category to declare the protocol conformance:

@interface MasterViewController () <DetailViewControllerDelegateProtocol>
@end

- (void)didFinishTask:(DetailViewController *)sender {
  // do stuff like updating the UI
}

For the Swift equivalent code we can use an extension to the master view controller class to declare and implement the delegate function:

extension MasterViewController: DetailViewControllerDelegate {
  func didFinishTask(sender: DetailViewController) {
    // do stuff like updating the UI
  }
}

We also need to remember to set the delegate somewhere. This might be in a prepareForSegue or target-action method that will present the detail view controller:

// Objective-C
detailViewController.delegate = self;

// Swift
detailViewController.delegate = self

Calling Delegate Methods

Finally we can call the delegate from our delegating class. In Objective-C we avoid checking the delegate is set since sending a message to nil does no harm. (If you have optional methods use respondsToSelector: to first test if it is implemented by the delegate):

[self.delegate didFinishTask:self];

In Swift we can use optional chaining to achieve a similar effect. Only if the delegate is not nil do we call the delegate method:

delegate?.didFinishTask(self)

Further Reading

Never miss a post

iOS Size Classes Cheat Sheet

Subscribe and also get my free iOS Size Classes Cheat Sheet

Success! Now check your email to confirm your subscription and download your free guide to iOS Size Classes.

There was an error submitting your subscription. Please try again.

Unsubscribe at any time. See Privacy Policy
No time to watch WWDC videos?

Sign up to get my iOS posts and news direct to your inbox and also get my free iOS Size Classes Cheat Sheet

OK! Check your inbox (or spam folder) for an email to confirm your details and download your free guide to iOS Size Classes.

There was an error submitting your subscription. Please try again.

Unsubscribe at any time. See Privacy Policy
Archives Categories