在ARC下将代表设置为nil?

时间:2013-02-22 03:31:13

标签: ios delegates automatic-ref-counting

我正在使用ARC编写iOS应用程序,并以iOS 5 +为目标。

假设我编写了一个具有委托属性的自定义视图对象。在声明委托属性时,我将它作为一个弱引用来避免保留循环,这样当实际的委托对象(控制器)被销毁时,我的自定义视图也将被销毁,如下所示:

@interface MyCustomView : UIView

@property (nonatomic, weak) id<MyCustomViewDelegate> delegate;

@end

一切都很好。

好的,现在我正在编写控制器对象,它引用了两个视图对象:我的自定义视图和Apple提供的UIKit视图,两者都声明了委托属性,而控制器是两者的委托观点。也许它看起来像这样:

@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

我的问题是:我是否需要覆盖dealloc以将其中一个或两个委托设置为nil?

我的意思是,据我所知,UIKit视图的委托属性(在本例中为tableView)实际上并未声明为弱引用,而是__unsafe_unretained引用,与非ARC版本的iOS向后兼容。所以也许我需要写

- (void)dealloc
{
    _tableView.dataSource = nil;
    _tableView.delegate = nil;
}

现在,如果我必须覆盖dealloc,我仍然不必设置_customView.delegate = nil,对吗?因为(由我)声明它是一个弱引用,所以它应该在MyViewController被破坏时自动设置为nil。

但另一方面,我不是针对iOS的非ARC版本,我也不打算这样做。所以也许我根本不需要覆盖dealloc?

3 个答案:

答案 0 :(得分:30)

将非弱代表设置为nil通常是一个好主意,除非你知道你不需要。对于UITableViewUIScrollView,我在之前的iOS版本中遇到过以下步骤的崩溃(可能有助于在启用僵尸的情况下运行):

  1. 滚动得非常快。
  2. 按完成或后退按钮或其他任何一项以关闭VC。
  3. 这似乎是因为滚动动画保留了对视图的引用,因此视图比VC更长。它在发送滚动事件时崩溃。

    在加载请求时解除包含UIWebView的VC后,我也看到了崩溃,只是将委托设置为nil是不够的(我认为解决方法是调用[webView loadRequest:nil] )。

答案 1 :(得分:2)

如果对tableView唯一的引用是您唯一的MyViewController控制器,则无需手动设置UITableViewDelegate或{{1} } UITableViewDataSource

原因是,一旦nil上的dealloc方法被调用,tableview也将与控制器一起被销毁(也就是说,只要对它进行唯一的引用是你唯一的控制者MyViewController类。

如果您对此tableview有其他强引用,例如其他控制器,那么tableview可能会比MyViewController类存在更长时间。在这种情况下, 需要在{{{的dealloc方法中将MyViewControllerUITableViewDelegate设置为UITableViewDataSource 1}}因为,正如您所提到的,这些属性不是弱引用,不会自动设置为nil

然而,根据我的经验,这种情况非常罕见。

大多数时候,我并不担心将这些设置为MyViewController,但这是一种防御性的编程实践。

也请看这篇文章:

In dealloc method set any delegate to nil is needed or not needed

答案 2 :(得分:0)

您希望将delegatedataSource明确设置为nil的唯一原因是,customViewtableView是否可以在视图中生效控制器。将它们设置为nil可以防止delegatedataSource引用已解除分配的对象。

如果customViewtableView将与视图控制器一起取消分配,则无需忽略delegatedataSource