ViewController respondsToSelector:发送到解除分配实例的消息(CRASH)

时间:2012-06-23 15:18:08

标签: objective-c ios xcode crash

好的,这是交易,我讨厌提出有关我的调试和崩溃的问题。因为我自己经常处理它们,但我只是无法绕过这个,即使在已经查看了多个问题之后。

好的,这就是问题所在,我发现我的应用随机打开和关闭了这个堆栈跟踪:

*** -[ViewController respondsToSelector:]: message sent to deallocated instance 0x1e5d2ef0

ViewController可能会有所不同,有时我的代码崩溃的地方与该特定ViewController具有 NO 相关性,并且不拥有或调用它。

另外,为了获得控制台跟踪,我启用了Zombies,否则我根本就没有控制台打印,我只会得到:objc_msgSend,我知道这意味着我正在发布消息。但我找不到那个地方......我真的被卡住了!通常我总是调试我的崩溃,所以我真的坚持这个。

同样,这会在不同时间,不同时间,不同地点崩溃。它崩溃的地方几乎与<{1}} 没有相关。而且我觉得这很令人困惑。

你需要我的任何代码吗?我有很多的文件,因为它在不同的地方崩溃,分发我的代码会很乱!

我试图添加符号断点而没有运气,并且在iOS的Instruments应用程序中没有Zombies。我无法在模拟器上运行我的应用程序,因为它有不支持的架构框架。

谢谢大家......

7 个答案:

答案 0 :(得分:169)

使用 Instruments 来追踪已解除分配的实例错误。分析您的应用程序(Cmd⌘ + I )并选择 Zombies 模板。应用程序运行后,尝试使其崩溃。你应该得到类似的东西:

enter image description here

单击弹出窗口中地址旁边的箭头,显示解除分配后调用的对象。

enter image description here

您现在应该看到每个已更改的调用都会保留此对象的计数。这可能是因为发送直接保留/释放消息以及耗尽自动释放池或插入NSArrays。

RefCt 列显示调用操作后的retainCount, Responsible Caller 显示执行该操作的类名称和方法。当您双击任何保留/释放时,乐器将显示执行此操作的代码行(如果这不起作用,您可以通过选择它并在扩展详细信息中选择其对应项来检查调用窗格):

enter image description here

这将让您检查对象的所有 retainCount 生命周期,并且可能会立即找到您的问题。您要做的就是找不到保留以获取最新的发布

答案 1 :(得分:59)

有类似的问题。在我的情况下,viewController需要获取navigationController事件,因此它注册为导航控制器委托:

 self.navigationController.delegate = self;

当该控制器被解除分配但仍然是视图控制器的委托时发生崩溃。在dealloc中添加此代码无效:

-(void) dealloc
{
    if (self.navigationController.delegate == self)
    {
        self.navigationController.delegate = nil;
    }

因为在调用dealloc时,视图控制器已经从视图层次结构中删除,因此self.navigationController为nil,因此保证比较失败! : - (

解决方案是添加此代码以检测VC在实际执行之前离开视图层次结构。它使用iOS 5中引入的方法来确定视图何时被弹出而不被推送

-(void) viewWillDisappear:(BOOL) animated
{  
   [super viewWillDisappear:animated];
   if ([self isMovingFromParentViewController])
   {
      if (self.navigationController.delegate == self)
      {
           self.navigationController.delegate = nil;
      }
   }
}

不再崩溃!

答案 2 :(得分:4)

对于任何无法解决问题的人,以下是其他一些技巧:

https://stackoverflow.com/a/12264647/539149

https://stackoverflow.com/a/5698635/539149

https://stackoverflow.com/a/9359792/539149

https://stackoverflow.com/a/15270549/539149

https://stackoverflow.com/a/12098735/539149

您可以通过单击项目弹出窗口 - >编辑方案...配置文件 - &gt;仪器并选择分配或泄漏,然后配置应用程序,然后停止仪器,单击分配中的信息按钮,在Xcode 5中运行仪器。 “启用NSZombie Detection”。

但是,对于直接来自com.apple.main-thread的消息,这可能不会显示任何内容。

我把头撞了两个多小时,答案结果证明是一个过度释放,我通过蛮力评论我的项目副本发现,直到我找到罪魁祸首:

[viewController release];
viewController = NULL;

问题是release不会将变量设置为NULL。

这意味着将其设置为NULL会再次释放,减少引用计数并立即释放内存,直到稍后引用viewController的变量完成时。

因此要么启用ARC,要么确保您的项目始终使用release或NULL,但不能同时使用两者。我的偏好是使用NULL,因为那时没有机会引用僵尸,但是它会让查找对象释放的位置变得更加困难。

答案 3 :(得分:4)

我昨天在iOS遇到了同样的问题。我已经在App&#34;关于&#34; subview,我在&#34;关于&#34;中添加了Transaction Observer。 viewDidLoad中。当我第一次购买时没问题,但是在我回到主窗口并输入关于子视图再次购买之后,问题&#34;消息被发送到解除分配的实例&#34;发生了,应用程序崩溃了。

- (void)viewDidLoad
{
    [[SKPaymentQueue defaultQueue] addTransactionObserver:self];                                           object:nil];
}

在dealloc中删除Transaction Observer之后,问题就解决了。

- (void)dealloc
{
    // Even though we are using ARC, we still need to manually stop observing any
    // NSNotificationCenter notifications.  Otherwise we could get "zombie" crashes when
    // NSNotificationCenter tries to notify us after our -dealloc finished.

    [[SKPaymentQueue defaultQueue] removeTransactionObserver:self];
}

答案 4 :(得分:4)

我有一个非常类似的问题,我发现这是由于导航控制器代表设置。

以下解决了我的问题,

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];

    if (self.navigationController.delegate != self) {
        self.navigationController.delegate = self;
    }
}

-(void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];

    if (self.navigationController.delegate == self) {
        self.navigationController.delegate = nil;
    }
}

答案 5 :(得分:2)

在OS X中遇到同样的问题。

要解决这个问题,@ SoftwareEvolved已经说过- (void)dealloc方法了。但遗憾的是- (void)viewWillDisappear仅适用于版本10.10及更高版本。

我在我的NSViewController子类中引入了自定义方法,其中将所有zombie-dangerous引用设置为nil。在我的情况下,NSTableView属性(delegatedataSource)。

- (void)shutdown
{
  self.tableView.delegate = nil;
  self.tableView.dataSource = nil;
}

这就是全部。每次我要从superview中删除视图时,都需要调用此方法。

答案 6 :(得分:2)

我有同样的问题。很难找到哪个委托导致问题,因为它没有表明任何行或代码声明所以我尝试了某种方式,也许它对你有帮助。

  1. 打开xib文件,然后从文件所有者处选择“显示连接检查器”右侧菜单。列出了代表,将其设置为零,这些都是可疑的。
  2. (与我的情况相同)像Textfield这样的属性对象可以创建问题,因此将其委托设置为nil。
  3. Class<bool>