Mic*_*ler 5 iphone multithreading delegates core-data nsfetchedresultscontroller
首先,抱歉这个问题太久了.
我知道这里讨论类似问题的问题很少,但这些问题都没有谈到NSFetchedResultsController与委托以及单独线程中的更新.并没有一个解决方案帮助了我.
这些是现有的问题:
现在关于我的问题:
NSFetchedResultsController并且委托设置为self.有时我会was mutated while being enumerated在单独的线程中更新数据时收到异常,有时会崩溃应用程序.
我已经做了很多代码操作,试图修复它,似乎没有任何帮助.
我已经尝试不直接从表视图数据源方法使用托管对象.而不是我创建了一个包含字典列表的数组.我用didChangeObject上面的方法填写这些词典.这样我就不会在视图控制器中触摸托管对象了.
然后我明白问题出在NSFetchedResultsController中,可能一直在迭代数据.这是与单独线程中的数据更新冲突的对象.
问题是,一旦我有一个带委托的NSFetchedResultsController(意味着它"监视"数据并一直更新delagate),我如何更新单独线程中的核心数据对象.
NSFetchedResultsControllerDelegate实现:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
if ( self.tabBarController.selectedIndex == 0 ) {
UITableView *tableView = self.tableView;
@try {
switch(type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
@catch (NSException * e) {
NSLog(@"Exception in didChangeObject: %@", e);
}
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
if ( self.tabBarController.selectedIndex == 0 ) {
@try {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
@catch (NSException * e) {
NSLog(@"Exception in didChangeSection: %@", e);
}
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
Run Code Online (Sandbox Code Playgroud)
在表视图数据源方法中,我直接使用托管对象.
Mar*_*rra 12
Two separate questions here. First, if you are getting mutating errors that means you are mutating a set or array (or relationship) while iterating over that set/array/relationship. Find where you are doing that and stop doing it. That is the only solution.
As for your updates. Your background NSManagedObjectContext should be saving periodically. Your main thread should be listening for NSManagedObjectContextDidSaveNotification and when it receives one it calls the main NSManagedObjectContext on the main thread (as the notification will most likely come in on the background thread) via -mergeChangesFromContextDidSaveNotification: which takes the NSNotification as a parameter. This will cause all of your NSFetchedResultController instances to fire their delegate methods.
Simple as that.
ank you for your reply. The exception is thrown on updating the NSManagedObjectContext in the background thread. I use the same NSManagedObjectContext in both threads. The app should be as close as possible to real time app - the updates constantly and the tables should be updated immediately. I don't save at all - I only update the NSManagedObjectContext. I have seen in one of the questions mentioned that someone used to separate instances of NSManagedObjectContext but he still receive the same exceptions once he merges the changes. So, you suggest using 2 separate NSManagedObjectContext's?
First, read up on multi-threading in Core Data from Apple's documentation (or my book :).
Second, yes you should have one context per thread, that is one of the golden rules of Core Data and multi-threading (the other is don't pass NSManagedObject instances across threads). That is probably the source of your crash and if it isn't it is going to be the source of a crash in the future.
I have tons of data and I update only the modified/new/deleted items in the table. If I will start saving then will it harm the performance?
No, only the updates will be propagated across the threads. The entire data store will not be re-read so it will actually improve performance when you break up the saves into smaller chunks because you will be on the main thread, updating the UI, in smaller chunks so the UI will appear to perform better.
However, worrying about performance before the app is completed is a pre-optimization that should be avoided. Guessing at what is going to perform well and what won't is generally a bad idea.
| 归档时间: |
|
| 查看次数: |
3836 次 |
| 最近记录: |