【问题标题】:Custom dealloc and ARC (Objective-C)自定义 dealloc 和 ARC (Objective-C)
【发布时间】:2011-11-09 15:56:55
【问题描述】:

在我的小 iPad 应用程序中,我有一个使用观察者的“切换语言”功能。每个视图控制器都会在 viewDidLoad: 期间向我的观察者注册。

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

当用户点击“更改语言”按钮时,新语言将存储在我的模型中,并通知观察者并在其注册对象上调用 updateUi: 选择器。

这很好用,除非我在 TabBarController 中有视图控制器。这是因为当标签栏加载时,它会从其子控制器获取标签图标而不初始化视图,因此不会调用viewDidLoad:,因此这些视图控制器不会收到语言更改通知。因此,我将 registerObject: 调用移到了 init 方法中。

当我使用viewDidLoad: 向我的观察者注册时,我使用viewDidUnload: 取消注册。由于我现在在init 注册,因此在dealloc 中取消注册很有意义。

但这是我的问题。当我写:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

我收到此错误:

ARC 禁止“dealloc”的显式消息发送

由于我需要调用 [super dealloc] 以确保正确清理超类,但 ARC 禁止这样做,我现在陷入困境。当我的对象死亡时,还有其他方法可以得到通知吗?

【问题讨论】:

  • 附带说明 - 这样的情况可能会导致内存泄漏,这不会显示在泄漏工具中。如果 dataModel 保留对观察者的引用(这是 ARC 下的默认内容,即使对于 ivars 也是如此),则永远不会调用 dealloc,因为保留计数将大于零。因此,您可能必须手动取消注册观察者才能首先调用 dealloc。
  • 我为右手和左手选项实现了类似的东西。唯一需要该消息的 VC 是当前显示的那个。其他人在 viewDidLoad 或 viewDidAppear 中查看模型以对界面进行更改。也许这样的事情会更好。
  • @BlazejCzapp 因为他使用的是 UITabBarController,假设 UITabBarController 将始终持有对注册控制器的引用(我猜它的“子”控制器就是这种情况),内存泄漏会不会仍然是一个问题?我看不到注册的控制器何时会被分配。谢谢

标签: objective-c ios xcode dealloc automatic-ref-counting


【解决方案1】:

使用 ARC 时,您只需不显式调用 [super dealloc] - 编译器会为您处理它(如 Clang LLVM ARC document, chapter 7.1.2 中所述):

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

【讨论】:

  • 如果视图持有对观察者的引用,而观察者持有对视图的引用,那么我们就有了循环引用。因此视图的引用计数大于 0,并且永远不会调用 dealloc。在 dealloc 中调用 [observer unregisterObject:self] 有意义吗?我错过了什么?
  • 那就是工作。导致观察者本身持有对控制器的引用。这将防止首先调用 dealloc
猜你喜欢
  • 2012-07-21
  • 1970-01-01
  • 1970-01-01
  • 2014-03-22
  • 1970-01-01
  • 1970-01-01
  • 2010-10-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多