3

应用程序有时会因错误而崩溃objc_object::release()

苹果开发者技术支持提到了这一点:

请记住,您应该始终执行 _tableView.delegate = nil; 之类的操作。在您的 -dealloc 方法中,即使您使用的是 ARC。出于兼容性原因,系统对象使用unsafe_unretained 引用来实现委托,而不是首选的现代替换weak

这是否意味着当视图控制器即将被释放时,我必须将系统对象的代表设置为零?

class MyViewController: UIViewController {
   deinit {
      tableView.delegate = nil
      tableView.dataSource = nil
   }
}

我总是假设UITableView和类似的标准对象正在使用weak对其代表的引用?


更新:

技术支持的示例似乎已过时,因为UITableView已更新给weak代表。但是,并非所有代表都已更新,例如AVAudioPlayer.delegateis still unowned(unsafe)。看来,Apple 正在逐渐将代表更新为weak.

因此,可以通过检查 Xcode 中的委托声明来简单地确定委托是否已手动设置为 nil。如果是weak,请不要打扰。

4

1 回答 1

3

是的,您应该将这些代表设置为nil.

正如名称所暗示的那样,unsafe_unretained引用不会保留您的视图控制器,因此这里没有保留周期或内存泄漏。但是,与 不同的是,当您的视图控制器被释放时weak,这些引用不会自动设置为。nil在大多数情况下,这不是问题,因为您的视图控制器将比它的视图寿命更长,或者至少同时被释放。不幸的是,在少数情况下,UIKit 也可能暂时保留了视图。这可以让视图比视图控制器寿命更长,并尝试在已释放的对象上调用委托方法,从而导致崩溃。

我知道看到这一点的最简单方法是在滚动仍在滚动时(例如,通过强烈的滑动手势)关闭并取消分配一个视图控制器,该控制器是滚动视图(或其子类之一,如 UITableView)的委托一长串项目)。然后滚动视图将尝试调用scrollViewDidScroll已释放控制器上的委托方法(如 )。

于 2017-09-16T02:15:16.183 回答