【问题标题】:[UIViewController hash]: message sent to deallocated instance with ARC[UIViewController 哈希]:使用 ARC 发送到已释放实例的消息
【发布时间】:2012-04-09 13:18:29
【问题描述】:

无法解决这个问题,[UIViewController hash] 被发送到已正确释放的视图控制器,它被推送到导航然后随后弹出,然后在某个随机点发生这种情况。看起来 UIViewController 类有某种静态的视图控制器集合,其中对旧控制器的引用仍然被保留,尽管被删除了。

 206, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
    frame #0: 0x0225cdee CoreFoundation`___forwarding___ + 206
    frame #1: 0x0225ccb2 CoreFoundation`_CF_forwarding_prep_0 + 50
    frame #2: 0x017e1cd1 Foundation`objectHash + 33
    frame #3: 0x017e3444 Foundation`hashProbe + 47
    frame #4: 0x017f5d03 Foundation`-[NSConcreteHashTable hashGrow] + 217
    frame #5: 0x017e3407 Foundation`-[NSConcreteHashTable addObject:] + 136
    frame #6: 0x00f98089 UIKit`+[UIViewController setViewController:forView:] + 101
    frame #7: 0x00f94c71 UIKit`-[UIViewController setView:] + 542
    frame #8: 0x017ecf30 Foundation`_NSSetUsingKeyValueSetter + 77
    frame #9: 0x017ecedb Foundation`-[NSObject(NSKeyValueCoding) setValue:forKey:] + 287
    frame #10: 0x01807d50 Foundation`-[NSObject(NSKeyValueCoding) setValue:forKeyPath:] + 393
    frame #11: 0x010ef71a UIKit`-[UIRuntimeOutletConnection connect] + 106
    frame #12: 0x022f7dea CoreFoundation`-[NSObject performSelector:] + 58
    frame #13: 0x022617f1 CoreFoundation`-[NSArray makeObjectsPerformSelector:] + 273
    frame #14: 0x010ee26e UIKit`-[UINib instantiateWithOwner:options:] + 1178
    frame #15: 0x00f941fc UIKit`-[UIViewController _loadViewFromNibNamed:bundle:] + 286
    frame #16: 0x00f94779 UIKit`-[UIViewController loadView] + 302

它看起来像私有方法 [UIViewController setViewController:forView:],从 [UIViewController setView:] 调用,可能将每个视图控制器存储在视图的类级字典中 -> 视图控制器。稍后在向集合中添加另一个 VC 时,它需要增长,这会导致集合中的所有值都被重新散列,从而导致 [UIViewController hash] 调用 delloced VC。现在的问题是为什么 VC ref 还在那里?也许是因为视图在没有控制器委托的情况下仍然存在。

更新:尽管 VC 已被销毁,但在弹出 VC 后,我可以确认视图控制器的视图仍然存在。不过不太清楚为什么。

【问题讨论】:

  • 把你的代码放在这里或者自己释放内存而不是ARC
  • 这里的代码太多了,为什么还要自己释放内存呢?
  • 这里的代码太少,任何人都无法提供太多帮助。

标签: iphone automatic-ref-counting ios5


【解决方案1】:

哇,终于知道是什么了,非常糟糕的事情(拍了自己的手腕)。

我已经将一个抽象的 UIViewController 子类重构为 UIViewController 上的一个类别,做一些类似于 UINavigationController 的事情,它将导航相关的功能添加到 UIViewController。但我没有注意到的是我的 UIViewController 子类已经实现了 dealloc,所以一旦它被转换为一个类别,它就替换了 UIViewController 的 dealloc 方法。

你认为编译器会给我一个警告,如果你用 category 替换一个方法,它通常会这样做,但在 dealloc 的情况下似乎不会(可能与 ARC 代码生成有关)

【讨论】:

  • 正是我的问题,正是出于这个原因。 FWIW - 我没有使用 ARC,也没有收到任何警告。
【解决方案2】:

我不知道你为什么认为这很奇怪。 viewController 从堆栈中弹出后,可能需要从哈希表中删除才能释放。他们需要为此调用 hash 方法。 此外,出于性能原因,IOS 可能会保留 viewController 一段时间。如果再次需要它,他们将简单地调用 viewWillLoad: ,而不必实例化一个新的视图控制器。最重要的是,在 viewController 弹出后如何处理它是 Apple 的事情。

只有在 viewController 的 hash 方法在它的 release 方法之后被调用时,这才奇怪。你检查过吗?

【讨论】:

  • [UIViewController hash]: message sent to deallocated instance - 建议是这种情况
  • 啊,我不明白您的问题标题是您收到的实际错误消息。堆栈跟踪似乎表明您在哈希方法中设置了断点。
【解决方案3】:

你没有做太多的事情,但是如果 ARC 释放了视图控制器,我们可以(合理地)确信没有对它的强引用。 (这是合理的,因为如果您没有使用正确的命名约定,它可能会自动释放不应该这样做的实例。)

另外,由于它发生在一段时间后,我的猜测是第二个视图控制器启动了一些长时间运行的进程。委托指向同一个视图控制器。

当您弹出视图控制器时,长时间运行的进程仍在运行,当它完成时,委托不再指向正确的对象。

但是,正如我所说,这是一个完全的猜测,因为您没有发布任何代码。

【讨论】:

  • 嗨,斯蒂芬,感谢您有根据的猜测,没有长时间运行的进程,但我现在有一个理论来解释为什么它会崩溃。我已经更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-13
  • 2011-08-16
  • 2011-12-17
  • 2011-06-16
相关资源
最近更新 更多