14

我正在使用 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 以将一个或两个代表设置为零?

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

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

现在,如果我必须重写 dealloc,我仍然不必设置_customView.delegate = nil,对吗?因为那被(我)声明为弱引用,所以它应该在销毁时自动设置为 nil MyViewController

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

4

3 回答 3

30

将非弱委托设置为 nil 通常是一个好主意,除非您知道不必这样做。对于UITableViewUIScrollView,我在以前的 iOS 版本上经历了以下步骤的崩溃(它可能有助于在启用僵尸的情况下运行):

  1. 滚动真的很快。
  2. 按完成或后退按钮或其他任何关闭 VC。

这似乎是因为滚动动画保留了对视图的引用,因此视图比 VC 寿命更长。它在发送滚动事件时崩溃。

在关闭包含一段时间的请求正在加载的 VC 后,我还看到崩溃UIWebView,其中仅将委托设置为 nil 是不够的(我认为解决方法是调用[webView loadRequest:nil])。

于 2013-02-22T04:06:22.783 回答
2

如果对 say 的唯一引用tableView是您的唯一MyViewController控制器,则无需手动设置UITableViewDelegateUITableViewDataSourceto nil

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

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

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

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

另见这篇文章:

在 dealloc 方法中,需要或不需要任何委托到 nil

于 2013-02-22T03:41:57.987 回答
0

您想要显式设置delegateanddataSource的唯一原因nil是如果 thecustomView或 thetableView可以在视图控制器中存活。将它们设置为nil将防止delegatedataSource引用已释放的对象。

如果customViewandtableView将与视图控制器一起被释放,则无需将delegateand清零dataSource

于 2013-02-22T03:37:58.547 回答