ios ViewController RespondsToSelector:消息发送到释放实例(崩溃)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11170614/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 18:54:54  来源:igfitidea点击:

ViewController respondsToSelector: message sent to deallocated instance (CRASH)

objective-ciosxcodecrash

提问by MCKapur

Ok, here is the deal, I hateputting out questions about my debugging and crashes. Because I usually handle them myself, but I just cannotget my way around this, even after viewing multiple questions already.

好的,这是交易,我讨厌提出有关我的调试和崩溃的问题。因为我平时处理他们自己,但我不能让我的身边这样一来,即使在已经观看多个问题

Ok so here is the problem, I find my app randomly on and off crashing with this stack trace:

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

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

Where ViewControllercan vary, sometimes the place where my code crashes, has NOrelevance to that particular ViewControllerand doesn't own or call it.

在哪里ViewController可以有所不同,有时会在我的代码崩溃的地方,有关联到特定的ViewController和并不拥有或调用它。

Also, to get that console trace, I have enabled Zombies, otherwise I would get no console print at all, I would only get: objc_msgSend, which I know means I am messaging something that is released. But I cannot find where that is... I am really stuck! Usually I alwaysdebug my crashes, so I am really stuck on this.

另外,为了获得控制台跟踪,我启用了 Zombies,否则我根本不会得到控制台打印,我只会得到: objc_msgSend,我知道这意味着我正在向已发布的内容发送消息。但我找不到那是哪里……我真的被卡住了!通常我总是调试我的崩溃,所以我真的坚持这一点。

Again, this crashes in different places at different times, on and off. And the place it crashes has almost norelevance to the ViewController. And I find this very confusing.

同样,这会在不同的时间、断断续续地在不同的地方崩溃。而且它崩溃的地方几乎没有相关性的ViewController。我觉得这很令人困惑。

Do you need any of my code? I have a lotof files and since it is crashing in different places, distributing my code will be a mess!

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

I have tried to add symbolic breakpoints with no luck, and Zombies is not available on the Instruments application for iOS. I cannot run my app on the simulator as it has unsupportive architecture frameworks for it.

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

Thanks everyone...

谢谢大家...

回答by Johnnywho

Use Instrumentsto track down deallocated instance errors. Profile your application (Cmd ?+I) and choose Zombiestemplate. After your application is running, try to crash it. You should get something like that:

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

enter image description here

在此处输入图片说明

Click on the arrow next to address in the popover to show object that was called after it was deallocated.

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

enter image description here

在此处输入图片说明

You should see now every call that has changed retain count of this object. This could be because sending directly retain/release messages as well as draining autorelease pools or inserting into NSArrays.

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

RefCtcolumn shows retainCount after action was invoked and Responsible Callershows class name and method in which it was performed. When you double click on any retain/release, instruments will show you line of code where this was performed (If this isn't working, you can examine call by selecting it and choosing its counterpart in Extended Detailpane):

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

enter image description here

在此处输入图片说明

This will let you examine all the retainCountlifecycle of object and probably you'll find your problem right away. All you got to do is find missing retainfor latest release.

这将让您检查对象的所有retainCount生命周期,并且您可能会立即发现您的问题。您所要做的就是找到最新版本缺少的retain

回答by software evolved

had a similar problem. In my case a viewController needed to get navigationController events, so it was registering as the navigation controller delegate:

有一个类似的问题。在我的例子中,viewController 需要获取 navigationController 事件,所以它注册为导航控制器委托:

 self.navigationController.delegate = self;

The crash occurs when that controller was dealloc'ed but was still the delegate for the view controller. Adding this code in dealloc had no effect:

当该控制器被释放但仍然是视图控制器的委托时,就会发生崩溃。在 dealloc 中添加此代码无效:

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

because at the point that dealloc is called, the view controller has already been removed from the view hierarchy, so self.navigationController is nil, so the comparison is guaranteed to fail! :-(

因为在调用 dealloc 时,视图控制器已经从视图层次结构中移除,所以 self.navigationController 为 nil,所以比较肯定会失败!:-(

The solution was to add this code to detect the VC leaving the view hierarchy just before it actually does so. It uses a method introduced in iOS 5 to determine when the view is being pop'ed and not pushed

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

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

No more crashes!

没有更多的崩溃!

回答by Zack Morris

For anyone who can't solve it, here are some other techniques:

对于无法解决的任何人,这里有一些其他技巧:

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

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

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

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

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

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

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

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

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

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

You can run Instruments in Xcode 5 by clicking the project popup->Edit Scheme...Profile ->Instrument and choose Allocations or Leaks, then profile your app, then stop Instruments, click the info button in Allocations and "Enable NSZombie Detection".

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

However, for the messages that come directly from the com.apple.main-thread, this probably won't reveal anything.

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

I banged my head on this for over two hours and the answer turned out to be an over-release, which I discovered by commenting out a copy of my project by brute force until I found the culprit:

我在这个问题上敲了两个多小时,结果发现答案是过度发布,我通过使用蛮力注释掉我的项目副本,直到找到罪魁祸首才发现了这一点:

[viewController release];
viewController = NULL;

The problem is that release doesn't set the variable to NULL.

问题是 release 没有将变量设置为 NULL。

That means that setting it to NULL calls release again, decrementing the refcount and freeing the memory immediately until later when the variables that reference viewController are finished with it.

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

So either enable ARC or make sure your project consistently uses release or NULL but not both. My preference is to use NULL because then there is no chance of referencing a zombie but it makes finding where objects are released more difficult.

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

回答by Ouyang Yong

I had met the same problem in iOS yesterday. I have made IAP in App "About" subview, and I have added Transaction Observer in "About" viewDidLoad. When I purchase for the first time, no problem, but after I back to main window and enter about subview to purchase again, the problem "message sent to deallocated instance" happened, and the App crashed.

我昨天在 iOS 中遇到了同样的问题。我在应用程序“关于”子视图中创建了 IAP,并在“关于”视图中添加了事务观察器。第一次购买时没问题,但是回到主窗口再次进入about subview购买后,出现了“message sent to deallocated instance”的问题,App崩溃了。

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

After I remove Transaction Observer in dealloc, the problem is solved.

我把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];
}

回答by thatzprem

I had a very similar issue and I figured out it was due to navigation controller delegates set.

我有一个非常相似的问题,我发现这是由于设置了导航控制器委托。

The below solved my issue,

下面解决了我的问题,

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

回答by nadim

I had the same Problem.It was difficult to find which delegate cause issue, because it does not indicate any line or code statement So I have try some way, Maybe it becomes helpful to you.

我有同样的问题。很难找到哪个委托导致问题,因为它没有指示任何行或代码语句所以我尝试了一些方法,也许它对你有帮助。

  1. Open xib file and from file's owner, Select "show the connections inspector" right hand side menu. Delegates are listed, set them to nil which are suspected.
  2. (Same as my case)Property Object like Textfield can create issue, So set its delegates to nil.
  1. 打开 xib 文件并从文件所有者处选择“显示连接检查器”右侧菜单。列出了代表,将它们设置为 nil 是可疑的。
  2. (与我的情况相同)像 Textfield 这样的属性对象会产生问题,因此将其委托设置为 nil。
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}
-(void) viewWillDisappear:(BOOL) animated{

[super viewWillDisappear:animated];

if ([self isMovingFromParentViewController]){

self.countryTextField.delegate = nil;

self.stateTextField.delegate = nil;

}

}

回答by Astoria

Had the same problem in OS X.

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

To solve this not enough - (void)deallocmethod as @SoftwareEvolved already said. But unfortunately - (void)viewWillDisappearis available only on version 10.10 and later.

- (void)dealloc正如@SoftwareEvolved 已经说过的那样,要解决这个不够用的方法。但不幸的- (void)viewWillDisappear是,仅适用于 10.10 及更高版本。

I introduced custom method in my NSViewController subclass where set all the zombie-dangerous references to nil. In my case that was NSTableViewproperties (delegateand dataSource).

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

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

That's all. Each time I'm about to remove view from the superview need call this method.

就这样。每次我要从超级视图中删除视图时都需要调用此方法。