Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
204 views
in Technique[技术] by (71.8m points)

ios - Set delegates to nil under ARC?

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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):

  1. Scroll really fast.
  2. 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]).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...