即使未保存上下文,NSFetchedResultsController委托也会被触发

时间:2012-08-29 19:03:36

标签: objective-c core-data nsfetchedresultscontroller

我有一个NSManagedObject实体,它覆盖validateForInsert和validateForUpdate。

根据我写的一些逻辑,当对象一致性出现问题时,此方法会正确返回NO。

该应用程序是一个经典的uitableview,由NSFetchedResultsController支持,带有详细视图控制器。

当我添加新实体时,详细视图控制器使用nil objectID进行实例化,并推送到导航堆栈中。 当我弹出详细控制器时,调用[context save:& error],并且通过放置一些断点,我发现当我添加一个新实体时,即使validateForInsert返回NO,并且includePendingChanges是,也会触发一次获取的委托方法。也设定为NO。

当我再次尝试再次弹出详细控制器时,保存当然会再次调用,也就是验证方法,但这次NSFetchedResultsControllerDelegate不会被触发。

我想知道这是否是正常行为,或者我是否遗漏了模型中的某些内容。

[UPDATE]

这是委托方法中断点之后的堆栈跟踪:

#0  0x0003e5ba in -[MyTableViewController controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:] at ......
#1  0x011512f9 in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()
#2  0x00b46a29 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#3  0x01759855 in ___CFXNotificationPost_block_invoke_0 ()
#4  0x01759778 in _CFXNotificationPost ()
#5  0x00a8b19a in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#6  0x0106a673 in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] ()
#7  0x01101f5e in -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] ()
#8  0x01065ad3 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] ()
#9  0x0106916b in -[NSManagedObjectContext save:] ()
#10 0x00004490 in -[MyAppDelegate saveContext:]

可以看出,即使在上下文中调用了save,也不会调用validate,因此这会使得获取的控制器委托被触发。

[更新2]

特别是,不知道它是否相关,这是在controllerDidChangeObject中导致异常(并不总是):

  

CoreData:错误:严重的应用程序错误。抓住了一个例外   在调用期间来自NSFetchedResultsController的委托   -controllerDidChangeContent :.无效更新:第0部分中的行数无效。现有部分中包含的行数   更新后(4)必须等于包含的行数   更新前的那一节(3),加上或减去行数   插入或删除该部分(0插入,0删除)和加号   或减去移入或移出该部分的行数(0移动   in,0搬出去了)。 with userInfo(null)

并且origin表中的infact有三行,只是因为当在上下文中创建对象时上下文绕过validateFor方法似乎插入了一行,行号中存在不一致。

控制器委托非常简单和标准:

-(void)controllerWillChangeContent:(NSFetchedResultsController*)controller {
   [self.tableView beginUpdates];
}

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
   // for testing purpose I am not doing any modification
   return;
}

-(void)controllerDidChangeContent:(NSFetchedResultsController*)controller {
   [self.tableView endUpdates];
}

我仍然不知道谁正在更新表格视图

1 个答案:

答案 0 :(得分:7)

我认为这是正常行为;获取的结果控制器在显示更改之前不需要保存。如果您不希望在详细信息视图中进行的更改在保存之前显示在主数据库中,则必须为详细信息视图创建单独的NSManagedObject上下文。这样,只有保存到持久存储的对象才会返回到获取的结果控制器。