我有CoreData
和表與相關的NSFetchedResultsController
。控制器具有在主隊列中創建並且只能讀取的上下文。當然,tableviewcontroller
實現NSFetchedResultsControllerDelegate
協議。NSFetchedResultsControllerDelegate在GCD託管環境中的不可理解的行爲
看看在方法,它實現:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
switch (type) {
case NSFetchedResultsChangeInsert:
NSLog(@"Inserted in %@", [NSString stringWithUTF8String:dispatch_queue_get_label(dispatch_get_current_queue())]);
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
NSLog(@"Updated in %@", [NSString stringWithUTF8String:dispatch_queue_get_label(dispatch_get_current_queue())]);
[_tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
在後臺我在我的應用程序下載數據並更新數據庫。數據庫的更新總是一樣的。它在我的數據管理方法更新:
- (void)saveDataInBackgroundInForeignContext:(void (^)(NSManagedObjectContext *))saveBlock completion:(void (^)(void))completion {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
dispatch_async([delegate.dispatcher queueForDataSavingInModel:self.modelName], ^{
[self saveDataInForeignContext:saveBlock];
dispatch_sync(dispatch_get_main_queue(), ^{
completion();
});
});
}
- (void)saveDataInForeignContext:(void (^)(NSManagedObjectContext *))saveBlock {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
NSManagedObjectContext *localContext = [[NSManagedObjectContext alloc] init];
[localContext setPersistentStoreCoordinator:coordinator];
[localContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[self.managedObjectContext setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy];
[[NSNotificationCenter defaultCenter] addObserver:self.managedObjectContext
selector:@selector(mergeChangesFromContextDidSaveNotification:)
name:NSManagedObjectContextDidSaveNotification
object:localContext];
saveBlock(localContext);
if (localContext.hasChanges) {
[self updateLastUpdateDateInConformedUpdatedObjects:localContext];
NSError *error = nil;
BOOL success = [localContext save:&error];
if (!success) {
NSLog(@"Saving in foreign context failed. %@", error.userInfo);
}
}
[localContext release];
}
}
在saveBlock
我修改方面依賴於從服務器的數據。 所以,在結果我有奇怪的行爲:
請注意第controller:didChangeObject:atIndexPath
NSLog
第一列表中的方法。讓我們看看日誌:
2012-11-16 02:59:33.376 [27824:5303] Inserted in ru.idecide.saving.calls // WTF WHY?!
2012-11-16 03:05:56.219 [27824:c07] Updated in com.apple.main-thread
ru.idecide.saving.calls - queue
保存數據。
這並不重要,一切正常,但方法insertRowsAtIndexPaths
在插入和(顯然)立即更新後在2-3秒內對UI有影響。爲什麼它會發生,我能做些什麼來避免它?
非常感謝,羅布。我想給你的答案投票,但是在這裏新來的,並且爲此留下了小名聲,請稍後再嘗試。 –
@AlexeyRogatkin沒問題。很高興我能幫上忙。 –
你現在爲什麼在更新的主線程中工作? –