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.

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: class {
  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 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.
No time to watch WWDC videos?

Sign up to get my iOS posts direct to your inbox and I will send you a free PDF of my 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.
Archives Categories