Sér*_*gio 8 core-data nsfetchedresultscontroller ios
我有一个像这样的coredata模型设置:
TileList <->> TileListOrder
TileListOrder <<-> Tile
Run Code Online (Sandbox Code Playgroud)
并创建了一个NSFetchedResultsController:
NSPredicate* predicate = [NSPredicate predicateWithFormat:@"tile <> nil AND tileList <> nil AND tile.removed == 0 AND tileList.removed == 0"];
NSSortDescriptor* sortTileListDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"tileList.order" ascending:YES] autorelease];
NSSortDescriptor* sortTileDescriptor = [[[NSSortDescriptor alloc] initWithKey:@"order" ascending:YES] autorelease];
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setPredicate:predicate];
[fetchRequest setSortDescriptors:sortDescriptors];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"TileListOrder" inManagedObjectContext:coreManagedObjectContext];
[fetchRequest setEntity:entity];
NSFetchedResultsController* fetchedResults = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:coreManagedObjectContext
sectionNameKeyPath:@"tileList.order"
cacheName:nil];
Run Code Online (Sandbox Code Playgroud)
我还在辅助NSManagedObjectContext上导入数据并将这些更改合并回来,如下所示:
- (void) localContextDidSave:(NSNotification*) notification {
dispatch_sync(dispatch_get_main_queue(), ^{
[coreManagedObjectContext mergeChangesFromContextDidSaveNotification:notification];
[self didSaveModelToCoreDataPersistentStore];
});
[super didEndUpdatingObjectInBackgroundThread];
}
Run Code Online (Sandbox Code Playgroud)
我正在添加和删除TileListOrders对象.它以6个对象和3个部分开始,当我完成时,删除6个原始对象并插入6个新对象.
现在我的问题是在NSFetchedResultsController委托上,它被调用右侧aftter mergeChangesFromContextDidSaveNotification:notification
-(void)controllerDidChangeContent:(NSFetchedResultsController *)controller{
NSLog(@"controller has %d sections, %d results:",[[controller sections] count], [[controller fetchedObjects] count]);
}
Run Code Online (Sandbox Code Playgroud)
在第一次打印12个对象和3个部分时被称为TWICE,第二次在3个部分中被称为6个对象.
在检查fetchedObjects时,第一次有6个插入的对象加上其他6个被删除的原始对象.它第二次包含3个部分中预期的6个对象.
看着:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath{
}
Run Code Online (Sandbox Code Playgroud)
第一次调用controllerDidChangeContent时,只处理了NSFetchedResultsChangeInsert更改,并且第二次只有NSFetchedResultsChangeDelete更改.
我预计只有在处理完所有更改后才会调用controllerDidChangeContent.如果这是驱动tableView那么这意味着tableview将动画两次.一次为插入的项目,另一次为已删除的项目.问题是第一次调用controllerDidChangeContent NSFetchedResultsController中被删除但仍存在于结果数组中的对象现在具有无效的属性值,因此显示这些项的tableView可能会崩溃.
任何人都知道如何使更改合并,以便在mergeChangesFromContextDidSaveNotification通知之后仅调用controllerDidChangeContent?
----------- 更新 ---------------
更多信息.
我只是观察NSManagedObjectContextDidSaveNotification,而localContextDidSave只被调用一次.
NSNotificationCenter* defaultCenter = [NSNotificationCenter defaultCenter];
[defaultCenter addObserver:self selector:@selector(localContextDidSave:) name:NSManagedObjectContextDidSaveNotification object:managedObjectContext];
Run Code Online (Sandbox Code Playgroud)
这是堆栈跟踪.第一次调用controllerDidChangeContent时,仅报告与INSERTED对象相关的更改,并且NSFetchedResultsController结果中仍然存在已删除的对象.如你所见,它是由触发的
#0 0x001fb735 in -[HomeViewController controllerDidChangeContent:]
#1 0x02947f9a in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()
#2 0x022d34f9 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#3 0x02e1c0c5 in ___CFXNotificationPost_block_invoke_0 ()
#4 0x02d76efa in _CFXNotificationPost ()
#5 0x02207bb2 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#6 0x0285a163 in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] ()
#7 0x0286dc71 in -[NSManagedObjectContext _mergeChangesFromDidSaveDictionary:usingObjectIDs:] ()
#8 0x0286ce2e in -[NSManagedObjectContext mergeChangesFromContextDidSaveNotification:] ()
#9 0x00044be2 in __50-[CoreDataUpdateableObject localContextDidSave:]_block_invoke
#10 0x0306f731 in _dispatch_barrier_sync_f_slow_invoke ()
#11 0x0307e014 in _dispatch_client_callout ()
#12 0x0306e7d5 in _dispatch_main_queue_callback_4CF ()
#13 0x02d68af5 in __CFRunLoopRun ()
#14 0x02d67f44 in CFRunLoopRunSpecific ()
#15 0x02d67e1b in CFRunLoopRunInMode ()
#16 0x038617e3 in GSEventRunModal ()
#17 0x03861668 in GSEventRun ()
#18 0x01756ffc in UIApplicationMain ()
#19 0x000022c6 in main
Run Code Online (Sandbox Code Playgroud)
第二次调用controllerDidChangeContent时,堆栈跟踪是:
#0 0x001fb735 in -[HomeViewController controllerDidChangeContent:]
#1 0x02947f9a in -[NSFetchedResultsController(PrivateMethods) _managedObjectContextDidChange:] ()
#2 0x022d34f9 in __57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 ()
#3 0x02e1c0c5 in ___CFXNotificationPost_block_invoke_0 ()
#4 0x02d76efa in _CFXNotificationPost ()
#5 0x02207bb2 in -[NSNotificationCenter postNotificationName:object:userInfo:] ()
#6 0x0285a163 in -[NSManagedObjectContext(_NSInternalNotificationHandling) _postObjectsDidChangeNotificationWithUserInfo:] ()
#7 0x028f3d2f in -[NSManagedObjectContext(_NSInternalChangeProcessing) _createAndPostChangeNotification:withDeletions:withUpdates:withRefreshes:] ()
#8 0x02855596 in -[NSManagedObjectContext(_NSInternalChangeProcessing) _processRecentChanges:] ()
#9 0x02854869 in -[NSManagedObjectContext processPendingChanges] ()
#10 0x02828e38 in _performRunLoopAction ()
#11 0x02d8aafe in __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ ()
#12 0x02d8aa3d in __CFRunLoopDoObservers ()
#13 0x02d687c2 in __CFRunLoopRun ()
#14 0x02d67f44 in CFRunLoopRunSpecific ()
#15 0x02d67e1b in CFRunLoopRunInMode ()
#16 0x038617e3 in GSEventRunModal ()
#17 0x03861668 in GSEventRun ()
#18 0x01756ffc in UIApplicationMain ()
#19 0x000022c6 in main
Run Code Online (Sandbox Code Playgroud)
这次它由以下触发:[NSManagedObjectContext processPendingChanges]()第二次NSFetchedResultsController结果实际上具有所需的状态:已删除的对象被删除,插入的对象存在.
我的问题是第一个mergeChanges应该触发controllerWillChangeContent和更改的结果,因此结果应该处于一致状态.
从发布的原始代码中我添加了一个[coreManagedObjectContext processPendingChanges]; 之后[coreManagedObjectContext mergeChangesFromContextDidSaveNotification:notification]; 因为没有这个,第二次调用只会在下一次运行runloop时触发.
我也试过[coreManagedObjectContext setPropagatesDeletesAtEndOfEvent:NO]; 但行为是一样的.删除的对象仅在第二次调用中删除.
| 归档时间: |
|
| 查看次数: |
1593 次 |
| 最近记录: |