ARC 中的系统对象委托是否需要设置为 nil?

Do system object delegates in ARC need to be set to nil?

应用程序有时会崩溃并出现错误 objc_object::release()

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

Remember that you should always do something like _tableView.delegate = nil; in your -dealloc methods, even if you are using ARC. For compatibility reasons system objects use unsafe_unretained references to implement delegation, instead of the preferred modern replacement weak.

这是否意味着我必须在视图控制器即将释放时将系统对象的委托设置为 nil?

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

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


更新:

技术支持的示例似乎已经过时,因为 UITableView 已经更新为 weak 代表。然而,并非所有代表都已更新,例如AVAudioPlayer.delegate 仍然是 unowned(unsafe)。 Apple 似乎正在逐渐将代表更新为 weak.

至于委托是否被手动设置为nil,可以通过检查Xcode中的委托声明来判断。如果是weak,请不要打扰。

是的,您应该将这些委托设置为 nil

顾名思义,unsafe_unretained 引用不会保留您的视图控制器,因此这里没有保留循环或内存泄漏。但是,与 weak 不同的是,当您的视图控制器被释放时,这些引用不会自动设置为 nil。在大多数情况下,这不是问题,因为您的视图控制器将比其视图寿命更长,或者至少同时被释放。 不幸的是,在少数情况下 UIKit 可能还临时保留了视图。这可能会导致视图比视图控制器的寿命更长,并尝试在已释放的对象上调用委托方法,从而导致崩溃。

我所知道的最简单的方法是在滚动仍在滚动时(例如从在一长串项目上用力滑动手势)。然后,滚动视图将尝试在已释放的控制器上调用委托方法(如 scrollViewDidScroll)。