1

好事实:

  • 我从服务器下载数据,并通过 Core Data 线程限制保存数据,当后台 MOC 被保存时,主 MOC 被合并。
  • 所有的保存操作都正常
  • MOC的合并也没有任何问题

我正在寻找的错误:

  • 当我的带有 NSFetchedResultsController 的 UITableView 处于活动状态(即在屏幕上)并且正在保存时,应用程序崩溃并出现 SIGABRT,它将我带到 AppDelegate 中的 mergeChangesFromContextDidSaveNotification 行。
  • 最奇怪的是,当 FRC 的委托为 nil 时,或者当它是我的视图控制器但我没有实现任何 FRC 委托方法时,不会发生崩溃并且我没有任何问题. 但是当我实现任何委托方法(甚至是空的,没有一行代码)时,应用程序会因相同的错误而崩溃。这意味着这些方法甚至没有被触发,问题不在于这些方法内部的代码
  • 最奇怪的第 2 部分(检查下面的更新 2):崩溃发生在 a[__NSCFNumber length]: unrecognized selector sent to instance并且我在我的 CoreDataManager 中也没有在我的 AppDelegate 类中调用任何“长度”属性

证人:控制台

<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(355)> Did merge
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<AppDelegate.m:(355)> Did merge
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<MyTableViewController.m:(134)> Fetched results controller did fetch 
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<CoreDataManager.m:(338)> Saved data from server
<AppDelegate.m:(352)> Will merge
<CoreDataManager.m:(338)> Saved data from server
[__NSCFNumber length]: unrecognized selector sent to instance 0x13318050

一些代码 - 合并 MOC

- (void)managedObjectContextDidSave:(NSNotification *)notification
{
    NSManagedObjectContext *sender = (NSManagedObjectContext *)[notification object];

    if ((sender != self.managedObjectContext) &&
        (sender.persistentStoreCoordinator == self.managedObjectContext.persistentStoreCoordinator))
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            DebugLog(@"Will merge");
            [self.managedObjectContext mergeChangesFromContextDidSaveNotification:notification];
            DebugLog(@"Did merge");
        });
    }
}

更新 1

按照 Cocoanetics 的提示,我创建了一个 NSNumber 类别来检查谁在调用length. 我得到了您在下面看到的内容,并且[__NSCFNumber _fastCStringContents:]: unrecognized selector sent to instance发生了崩溃。

在此处输入图像描述

更新 2 启用僵尸没有帮助 =(

4

5 回答 5

1

确保您只观察来自其他 MOC 的通知。如果你保存在那里,这会触发另一个这样的通知,并且你可能会进入一个无限循环,在一次或两次迭代后失败,因为一个对象已被 ARC 释放。

于 2012-11-08T12:28:26.377 回答
1

你的听起来像是内存问题。检查您的 ARC 所有权限定符并启用 NSZombies。启用 NSZombies 将帮助您缩小过早释放的对象。

当您启用僵尸时,您将看到“发送到已释放实例的消息”。检查哪个对象过早释放并更新您的问题。

于 2012-11-08T12:43:19.283 回答
1

好吧,经过几个月和几个小时,我终于找到了解决方案。它有效,我很想听听一些关于为什么的意见。

所以,正如我所说,节省工作 100%,以及合并通知。如果我将 NSFetchedResultsController 委托设置为 nil,则没有问题。但是,将委托设置为我的 UIViewController,导致应用程序崩溃。

我认为可能是因为我的代码触发了委托方法。但该应用程序甚至在此之前就崩溃了。因此,我按照 Cocoanetics 的提示创建了一个类别并尝试找出是谁在调用lengthNSNumber 对象的方法。在那之后,我看到 NSPredicate- (BOOL)evaluateWithObject:(id)object;在崩溃之前正在调用。同样,我做了一个类别来覆盖它:

@interface NSPredicate (PractiPredicate)
- (BOOL)evaluateWithObject:(id)object;
@end

@implementation NSPredicate (PractiPredicate)

- (BOOL)evaluateWithObject:(id)object
{
    NSLog(@"Evaluate was called. Object class %@", NSStringFromClass([object class]));
    MyManagedObject *myManagedObject = object;
    NSLog(@"Is fault? %d", myManagedObject.isFault);
    NSLog(@"myManagedObject changed and already have propertyA? %d", myManagedObject.propertyA != nil);
    return YES;
}

@end

因此,令我惊讶的是,它起作用了,并生成了以下日志:

评估被调用。对象类 MyManagedObject

是错吗?0

myManagedObject 已更改且已拥有 propertyA?1

我决定打印“是错吗?” 因为我认为这个混乱与 NSManagedObject 故障有关,但是,对于它打印的内容,它不是。

征求意见的问题:您认为这里可能会产生这个问题的原因是什么?

于 2013-01-08T14:36:53.403 回答
0

很可能问题不在于您发布的代码,而在于您如何处理获取的结果控制器委托中的更改。这些只是由合并触发。

于 2012-11-08T12:46:16.023 回答
0

我遇到了同样的问题,就我而言,我发现崩溃的原因是一个不正确的谓词。我有一个这样的谓词:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"attribute > 0"];

其中属性是一个字符串。我将其更正为:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"attribute.length > 0"];

现在,我的代码运行良好。确保检查代码中的所有谓词,因为这也可能是导致此崩溃的原因。

于 2014-09-19T05:06:01.450 回答