NSFetchedResultsController中的SIGABRT在mergeChangesFromContextDidSaveNotification之后委托方法

时间:2012-11-08 11:41:34

标签: ios core-data

好事实:

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

我狩猎的错误:

  • 当我的带有NSFetchedResultsController的UITableView处于活动状态时(即在屏幕上),并且正在进行保存时,应用程序崩溃了一个SIGABRT,它将我带到AppDelegate中的mergeChangesFromContextDidSaveNotification行。
  • 最奇怪的是,当FRC的代表是零时,或者当它是我的视图控制器但我没有实施任何FRC委托方法时,崩溃不会发生,我没有任何问题。但是当我实现任何委托方法(甚至是空的,没有一行代码)时,应用程序崩溃了同样的错误。 这意味着这些方法甚至没有被触发,问题不在于这些方法中的代码
  • 最奇怪的部分2 (下面检查更新2)[__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:]:无法识别的选择器发送到实例的崩溃。

enter image description here

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

5 个答案:

答案 0 :(得分:1)

确保您仅观察其他MOC的通知。如果你保存在那里,这会触发另一个这样的通知,你可能会在一次或两次迭代后无限循环,因为ARC已经释放了一个对象。

答案 1 :(得分:1)

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

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

答案 2 :(得分:1)

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

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

我认为可能是因为我的代码在触发委托方法时。但该应用程序甚至在此之前就崩溃了。所以我按照Cocoanetics提示创建了一个类别,并试图弄清楚谁在调用NSNumber对象的length方法。之后,我看到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

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

评论问题:您认为这可能会产生这个问题吗?

答案 3 :(得分:0)

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

答案 4 :(得分:0)

我有同样的问题,在我的情况下,我发现崩溃的原因是不正确的谓词。我有一个这样的谓词:

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

其中attribute是一个字符串。我把它更正为:

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

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