消息发送到解除分配的实例错误

The*_*0s3 4 objective-c ios

我不断收到一个错误,内容为*** -[NSKeyValueObservance retain]: message sent to deallocated instance 0x86c75f10. 我试过运行 Zombies 模板,这是它提供的截图。

在此处输入图片说明

它指向一个 managedObject,我在弄清楚对象在哪里被释放时遇到了麻烦。这是每次崩溃后编译器带我去的代码块。

- (void)setIsFavourite:(BOOL)isFavourite shouldPostToAnalytics:(BOOL)shouldPostToAnalytics;
{
    // check whether we need to generate preferences objects just in time
    if(!self.preferences && !self.series.preferences /*&& isFavourite*/)
    {
        if(self.series)
        {
            [self.series addPreferencesObject];
        }
        else
        {
            [self addPreferencesObject];
        }
    }

    //Crash In here
    self.preferences.isFavourite = @(isFavourite);
    self.series.preferences.isFavourite = @(isFavourite);
Run Code Online (Sandbox Code Playgroud)

编辑:如果您需要查看更大尺寸的图像,这里是一个更大分辨率的链接。

小智 5

好的,我遇到了类似的问题,并找到了一种使用 NSKeyValueObservance 调试此类问题的方法。要调试,请执行以下操作:

  1. 在 Xcode 中,打开“Breakpoint Navigator”。
  2. 添加一个新的符号断点: -[NSKeyValueObservance _initWithObserver:property:options:context:originalObservable:]
  3. 对于该断点,添加一个操作并将其设置为“调试器命令”。
  4. 设置以下命令: expr (void)NSLog(@"observer <0x%p>: %@ <%p>, property: %@", $arg1, (id)NSStringFromClass((id)[(id)$arg3 class]), $arg3, (id)$arg4)
  5. 单击“计算表达式后自动继续”。

现在您可以运行您的应用程序并采取必要的步骤来重现您的崩溃。是的,您需要启用 NSZombies。注意:它会运行得很慢,你会得到大量的调试输出,但请耐心等待。它最终会到达那里。

当您尝试向已解除分配的 NSKeyValueObservance 发送消息时遇到崩溃时,您将看到原始对象的地址。突出显示地址并点击 cmd-e 以在搜索缓冲区中输入文本。然后点击 cmd-g 在调试器输出中找到下一个出现的字符串。您可能会多次找到该地址,因此请查找observer <0x?????>输出后的地址。该行的输出应该告诉您正在观察什么对象以及哪个属性。

就我而言,当我把这一切都弄清楚后,结果发现我观察到一个依赖于数组中对象的合成属性,并且在某个操作期间,数组中对象的顺序发生了变化,而没有执行正确的 KVO 通知,这导致了我的崩溃。


Dun*_*n C 0

您使用手动引用计数吗?如果是这样,为什么?将您的应用程序转换为 ARC。手动引用计数充其量是痛苦的,而 ARC 则要好得多。

我是一位经验丰富的 iOS 和 Mac OS 开发人员,两者都可以,但我更喜欢 ARC。它不那么繁琐和容易出错。

Xcode 中内置了一项功能,可以将您的项目转换为 ARC。您可能需要做一些事后清理工作,但这是值得的。

如果你这样做,你的问题可能就会消失。

至于具体情况,您的屏幕截图太小,无法阅读。如果您希望有人尝试弄清楚发生了什么,您需要发布全尺寸的图像。

然而,从广义上讲,在我看来,您有一个自动释放错误。

在手动引用计数代码中,许多系统方法返回“自动释放”的对象。这意味着当您收到它们时,它们的保留计数为正数(通常为 1),因此它们会留下来。但是,它们已被添加到“自动释放池”中,这意味着如果没有人首先保留它们,它们将在下一次事件循环中被释放。

当您收到自动释放的对象时,您应该接受当前方法返回后它将被释放,或者保留它。

如果您尝试使用手动引用计数编写 Core Data 代码并且不理解这一点,那么您将面临失败。

Core Data 相当复杂,在尝试编写使用它的程序之前,您应该对 Cocoa 内存管理有深入的了解,特别是在您使用手动引用计数时。