Nik*_*rov 2 core-data objective-c nsfetchedresultscontroller nsmanagedobjectcontext ios
我在我的应用程序中处理数据导入部分,为了使UI更可靠,我按照Marcus Zarra的文章 http://www.cimgf.com/2011/08/22/importing-and-displaying-large -data集合核-数据/
我们的想法是你在后台的单独上下文中导入(我使用GCD),你的fetchedResultsController的上下文通过观察NSManagedObjectContextDidSaveNotification来合并更改.
我得到的问题对我来说很奇怪 - 我的fetchedResultsController没有获得那些更改,并且在新数据到来时不会重新加载TableView.但是,如果我触发以下方法,这使得获取和重新加载表 - 它在那里得到它.
- (void)updateUI
{
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
}
[self.tableView reloadData];
}
Run Code Online (Sandbox Code Playgroud)
所以现在我调用那个方法,当我得到NSManagedObjectContextDidSaveNotification使它工作,但它看起来很奇怪和讨厌我.
- (void)contextChanged:(NSNotification*)notification
{
if ([notification object] == [self managedObjectContext]) return;
if (![NSThread isMainThread]) {
[self performSelectorOnMainThread:@selector(contextChanged:) withObject:notification waitUntilDone:NO];
return;
}
[[self managedObjectContext] mergeChangesFromContextDidSaveNotification:notification];
//TODO:Make it work as it should - merge, without updateUI
[self updateUI];//!!!Want to get rid of this!
}
Run Code Online (Sandbox Code Playgroud)
为什么会这样?以下是负责解析数据和添加Observer的代码.
- (void)parseWordsFromServer:(NSNotification *)notification
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0) , ^{
NSDictionary *listInJSON = [notification userInfo];
wordsNumbers = [[listInJSON valueForKey:@"words"]mutableCopy];
if ([wordsNumbers count])
{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
Run Code Online (Sandbox Code Playgroud)
//新线程的新上下文NSManagedObjectContext*backContext = [[AppDelegate sharedAppDelegate] backManagedObjectContext];
//Get all the words we already have on this device
NSArray *wordsWeHave = [Word wordsWithNumbers:wordsNumbers inManagedContext:backContext];
//Add them to this list
for (Word *word in wordsWeHave)
[[List listWithID:[currentList listID] inManagedObjectContext:backContext]addWordsObject:word];
[backContext save:nil];!//Save the context - get the notification
}
});
}
Run Code Online (Sandbox Code Playgroud)
编辑
我NSFetchedResutsControllerDelegate
确实使用了,如果我不这样做,我怎么能假装我的tableview更新?
更新决定转移到父 - 子范式
这个问题已经讨论了很多次,比如NSFetchedResultsController没有显示来自不同上下文的更新,而且很难理解发生了什么,但我很少注意到.
首先,您违反了一个简单的规则:每个线程需要一个托管对象上下文(与核心数据部分并发).
为每个线程创建单独的托管对象上下文,并共享一个持久性存储协调器.
因此,在自定义线程内访问主上下文,获取其持久协调器并将其设置为新上下文.
NSManagedObjectContext *moc = [[NSManagedObjectContext alloc] init];
[moc setPersistentStoreCoordinator:persistentStoreCoordinatorGrabbedFromAppDelegate];
Run Code Online (Sandbox Code Playgroud)
其次,您不需要注册
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(contextChanged:) name:NSManagedObjectContextDidSaveNotification object:nil];
Run Code Online (Sandbox Code Playgroud)
在新线程内.只需在创建新线程的类(或应用程序委托)中注册它.
最后,如果您不使用NSFetchedResutsControllerDelegate
,请使用它.它允许摆脱重新加载数据表.当上下文发生变化时,委托会响应更改:编辑,删除,添加.
从iOS 5开始,您可以使用新的Core Data API,并通过新的限制机制让您的生活更轻松.
编辑
来自@mros评论.
它可以帮助您更多地了解使用父子核心数据模型的优势.我特别喜欢使用私有队列上下文来处理持久存储.请务必阅读整篇文章,因为一开始就说明了如何不这样做.
希望有所帮助.
归档时间: |
|
查看次数: |
1245 次 |
最近记录: |