-
Notifications
You must be signed in to change notification settings - Fork 4
Delegation
Define a protocol (interface) that describes the methods the delegate object must implement. The object that wants to get notified of a change registers itself as a delegate of a object via a property, typically called delegate.
In the object that needs to be notified, for instance a UIViewController.
BigCalculator is completly self contained and reusable. It does not know anything about UIViewControler1 object. It knows somewhere something is interested in receiving progress and results and that this thing implements the two methods defined in the BigCalculatorDelegate protocol.
With this pattern, UIViewControler1 knows about BigCalculator1, it owns it and holds a reference to it, it even created it.
- Delegation is one of the most used pattern in iOS. It works well and should be your default pattern for any "child notifies parent" of "child needs something from its parent" scenarios especially:
- View -> ViewController (unless that view exposes action handlers which are simpler to use, see the callbacks using selectors method).
- Databound collection View -> datasource
- ViewController -> parent ViewController
- It is simple to create and use (on both side of the communication), straightforward
- flexible thanks to @optional feature in obj-C protocols
- Technically you don't just notify the delegate something happened, you run code on your delegate. You can use this technique to retrieve data from it as well. In addition, if you have the need to wait for your delegate to finish what you told it to do, it is easy to implement unlike less coupled methods (KVO/NSNotification).
It does not work so well:
- when an object needs to notify multiple objects (since you can only have one delegate) e.g. a backend object just lost network connectivity and many different subsystems must adjust their UI as a result by becoming read-only.
- When the object that needs to be notified is far down the hierarchy chain e.g. you need to tell your great-great-great grand parent view controller that something changed. In this case, each one of the view controllers in the chain would have to implement delegation to pass the information all the way down).
- not asynchronous, last remark of pros, you do wait for your delegate to finish to do what you asked it to do.
- It can be somewhat verbose, a fair amount of code to write.
Always define the delegate property with a weak reference. A strong reference will most likely result in a retain loop, i.e. both the child object and its delegate object end up having strong references to each other and they are never freed.
GOOD
@property (nonatomic, weak) id<MyDelegateProtocol> delegate;
BAD
@property (nonatomic, strong) id<MyDelegateProtocol> delegate;
Always include yourself when you are notifying your delegate.
Since an object may be the delegate of multiple similar objects (e.g. the delegate of multiple UIButtons or multiple UIGestureRecognizer), you should define your protocol callbacks in a way that include yourself so the parent object can identify which child is sending the notification...
GOOD
-(void) studentEditor:(StudentEditorViewController *)editor didChangeFirstName:(NSString *) firstName;BAD
-(void) didChangeStudentName:(NSString *) firstName;inside the StudentViewController, whenever the first name is changed
[self.delegate studentEditor:self didChangeFirstName:self.firstnameTextField.text];Everything, everywhere, all the time (allmost). Pretty much all UI elements in iOS implement delegation and have a delegate property. The datasource property in UITableView and UICollectionView follow the exact same pattern with for instance a UITableViewDataSource protocol.