[UIViewController hash]:使用ARC发送到解除分配的实例的消息

时间:2012-03-26 00:38:21

标签: iphone automatic-ref-counting ios5

无法解决这个问题,[UIViewController哈希]被发送到一个已正确解除分配的视图控制器,它被推送到导航然后随后弹出,然后在某个随机点发生这种情况。看起来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 setView:]调用的私有方法[UIViewController setViewController:forView:]看起来将每个视图控制器存储在一个类级别的视图字典中 - >或许查看控制器。并且稍后在向集合中添加另一个VC时,它需要增长,这会导致所有值在集合中重新处理,从而导致对已解除定位的VC的[UIViewController hash]调用。现在问题是为什么VC ref仍在那里?也许是因为没有它的控制器委托,视图仍然存在。

更新:尽管VC被破坏,我可以确认在VC被弹出后视图控制器的视图仍然存在。不太清楚为什么会这样。

3 个答案:

答案 0 :(得分:3)

哇,很好地发现了什么是非常糟糕的东西(拍打自己的手腕)。

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

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

答案 1 :(得分:1)

你没有给予太多的帮助,但是如果ARC已经取消分配视图控制器,我们可以(合理地)确信没有强烈的引用它。 (合理的是因为如果你没有使用正确的命名约定,它可能会自动释放它不应该的实例。)

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

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

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

答案 2 :(得分:0)

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

如果在发布方法之后调用viewController的哈希方法,这只会很奇怪。你检查过了吗?