Set delegates to nil under ARC?

automatic-ref-counting, delegates, ios

Solution

Setting non-weak delegates to nil is generally a good idea unless you know you don't have to. For `UITableView` and `UIScrollView`, I've experienced crashes on previous iOS versions with the following steps (it may help to run with zombies enabled):

- Scroll really fast.

- Press Done or the back button or whatever to dismiss the VC.

This appears to happen because the scrolling animation is retaining a reference to the view, so the view outlives the VC. It crashes when sending the scroll event.

I've also seen crashes after dismissing a VC containing a `UIWebView` while a request is being loaded, where simply setting the delegate to nil was not sufficient (I think the workaround was to call `[webView loadRequest:nil]`).

Problem

I'm writing iOS apps using ARC and targeting iOS 5+. Suppose I write a custom view object that has a delegate property. In declaring the delegate property, I make it a weak reference to avoid a retain cycle, so that when the actual delegate object (the controller) is destroyed, my custom view will also be destroyed, as follows: ``` @interface MyCustomView : UIView @property (nonatomic, weak) id<MyCustomViewDelegate> delegate; @end ``` All is good. Ok, so now I'm writing the controller object, and it has references to two view objects: my custom view and an Apple-supplied UIKit view, both of which declare delegate properties, and the controller is the delegate for both views. Maybe it looks something like this: ``` @interface MyViewController : UIViewController <MyCustomViewDelegate, UITableViewDataSource, UITableViewDelegate> @property (nonatomic, strong) MyCustomView *customView; @property (nonatomic, strong) UITableView *tableView; @end @implementation MyViewController - (void)viewDidLoad { self.customView.delegate = self; self.tableView.dataSource = self; self.tableView.delegate = self; } @end ``` My question is this: Do I need to override dealloc to set either or both delegates to nil? I mean, as I understand it, the delegate property of the UIKit view (in this case, `tableView`) isn't actually declared to be a weak reference, but rather an `__unsafe_unretained` reference, for backwards compatibility with non-ARC version of iOS. So maybe I need to write ``` - (void)dealloc { _tableView.dataSource = nil; _tableView.delegate = nil; } ``` Now, if I do have to override dealloc, I still don't have to set `_customView.delegate = nil`, right? Because that was declared (by me) to be a weak reference, so it should be set to nil automatically upon the destruction of `MyViewController`. But on the other hand, I'm not targeting non-ARC versions of iOS, nor do I intend to. So maybe I don't need to override dealloc at all?

Original source