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

好的,这是交易,我讨厌提出有关我的debugging和崩溃的问题。 因为我通常自己处理它们,但即使在查看了多个问题之后,我也无法解决这个问题

好,所以这里是问题,我发现我的应用程序随机打开和closures堆栈跟踪崩溃:

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

在哪里ViewController可以改变,有时我的代码崩溃的地方, 没有相关的特定的ViewController ,并没有拥有或调用它。

此外,为了获得控制台跟踪,我已经启用僵尸,否则我将无法控制台打印,我只会得到: objc_msgSend ,我知道这意味着我正在发送消息的东西被释放。 但是我找不到那个地方…我真的被困住了! 通常我总是debugging我的崩溃,所以我真的坚持这一点。

再次,这在不同的时间,在不同的地方崩溃。 而它崩溃的地方几乎没有相关的ViewController 。 我觉得这很混乱。

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

我试图添加没有运气的符号断点,僵尸不适用于iOS的乐器应用程序。 我无法在模拟器上运行我的应用程序,因为它具有不支持的架构框架。

感谢大家…

使用工具来追踪解除分配的实例错误。 剖析您的应用程序( Cmd⌘ + I )并select“ 僵尸”模板。 应用程序运行后,尝试将其崩溃。 你应该得到这样的东西:

在这里输入图像描述

单击popup窗口中地址旁边的箭头以显示释放后调用的对象。

在这里输入图像描述

你现在应该看到每一个改变这个对象保留计数的调用。 这可能是因为发送直接保留/释放消息以及排空autorelease池或插入NSArrays。

RefCt列在调用操作后显示retainCount, Responsible Caller显示类名和执行操作的方法。 当您双击任何保留/发行版时,仪器会向您显示执行此操作的代码行(如果这不起作用,您可以通过select它并在“ 扩展详细信息”窗格中select其对应项来检查呼叫):

在这里输入图像描述

这将让你检查对象的所有retainCount生命周期,可能你会马上发现你的问题。 所有你需要做的是find失踪的保留最新版本

有类似的问题。 在我的情况下,一个viewController需要得到navigationController事件,所以它注册为导航控制器委托:

  self.navigationController.delegate = self; 

当控制器被释放,但是仍然是视图控制器的委托时发生崩溃。 在dealloc中添加这个代码没有任何影响:

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

因为在调用dealloc的时候,视图控制器已经从视图层次结构中删除,所以self.navigationController是零,所以比较保证失败! 🙁

解决方法是添加此代码来检测离开视图层次结构的VC,然后再实际执行。 它使用iOS 5中引入的方法来确定视图何时被popup而不被推送

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

没有更多的崩溃!

对于任何不能解决的人来说,这里有一些其他的技巧:

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

您可以通过点击项目popup – >编辑计划…configuration文件 – >仪器,然后select分配或泄漏,然后configuration您的应用程序,然后停止仪器,单击分配信息button和“启用NSZombie检测” 。

但是,对于直接来自com.apple.main-thread的消息,这可能不会透露任何东西。

我在这个问题上敲了两个多小时,结果竟然是一个过度释放,我通过强行发表了一个我的项目的副本,直到find罪魁祸首才发现:

 [viewController release]; viewController = NULL; 

问题是版本不会将该variables设置为NULL。

这意味着将其设置为NULL调用会再次释放,递减refcount并立即释放内存,直到稍后引用viewController的variables完成它为止。

所以要么启用ARC或确保您的项目一贯使用释放或NULL,但不是两者。 我的首选是使用NULL,因为那么没有引用僵尸的机会,但它使得发现对象被释放更困难。

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

以下解决了我的问题,

 - (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; } } 

我昨天在iOS遇到同样的问题。 我在应用程序“关于”子视图,我已经在“关于”viewDidLoad添加事务观察员。 当我第一次购买,没有问题,但是当我回到主窗口并进入子视图再次购买,问题“发送到释放实例的消息”发生,应用程序崩溃。

 - (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]; } 

在OS X中有相同的问题。

解决这个不够- (void)dealloc方法就像@SoftwareEvolved已经说过的那样。 但不幸的是- (void)viewWillDisappear仅在版本10.10及更高版本中可用。

我在我的NSViewController子类中引入了自定义方法,将所有僵尸危险的引用设置为nil。 在我的情况下,这是NSTableView属性( delegatedataSource )。

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

就这样。 每次我要从superview中移除视图时,都需要调用这个方法。

我有同样的问题。很难find哪个委托原因问题,因为它不表示任何行或代码语句所以我尝试了一些方法,也许它会对你有帮助。

  1. 打开xib文件并从文件所有者中select“显示连接检查器”右侧的菜单。 列出代表,将其设置为零。
  2. (和我的情况一样)像Textfield这样的Property对象可能会产生问题,所以将它的delegate设置为nil。
 -(void) viewWillDisappear:(BOOL) animated{ [super viewWillDisappear:animated]; if ([self isMovingFromParentViewController]){ self.countryTextField.delegate = nil; self.stateTextField.delegate = nil; } }