Core-Data executeFetchRequest在后台线程中冻结App
我有一个saveMOC
的直接父母的mainMOC
,我需要在线获取另一个tmpMOC
为了不阻止我的用户界面,同时从互联网上获取大量的logging。
我的应用程序冻结。 我可以缩小到这一点:
fetchedItems = [tmpMOC executeFetchRequest:fetchRequest error:&error];
我试图把这封装在dispatch_sync
, [moc.parentcontext.parentcontext.persistentStoreCoordinator lock/unlock]
, [whatevermoc performBlockAndWait]
…
我也试图取出_mainMOC
…没办法…
我明白, executeFetchRequest
是不是线程安全的,所以,我怎么locking我需要locking,以确保我没有插入一个双?
任何人都可以帮忙?
更新(1) AppDelegate中的_saveMOC
实例:
- (NSManagedObjectContext *)managedObjectContext { if (_mainMOC != nil) { return _mainMOC; } if (_saveMOC == nil) { NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; if (coordinator != nil) { _saveMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [_saveMOC setPersistentStoreCoordinator:coordinator]; [_saveMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; } } if (_mainMOC == nil) { _mainMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType]; [_mainMOC setParentContext:_saveMOC]; [_mainMOC setMergePolicy:NSMergeByPropertyStoreTrumpMergePolicy]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveContextChanges:) name:NSManagedObjectContextDidSaveNotification object:_mainMOC];
在MainViewController中创buildtemporaryMOC
MOC:
NSManagedObjectContext *temporaryContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; temporaryContext.parentContext = _mainMOC; [temporaryContext performBlock:^{ //AndWait NSError *error=nil; Feed *feed=(Feed *)[temporaryContext existingObjectWithID:feedID error:&error]; //... [RSSParser parseRSSFeedForRequest:req success:^(NSArray *feedItems) { NSLog(@"[MasterViewController::fetchPosts] inserting %d Posts.../OK", (int)[feedItems count]); feed.valid = [NSNumber numberWithBool:YES]; for(RSSItem *i in feedItems) { [self createPostInFeed:feed withTitle:i.title withContent:(i.content?i.content:i.itemDescription) withURL:[i.link absoluteString] withDate:(i.pubDate?i.pubDate:[NSDate date]) inMOC:temporaryContext]; } [[NSNotificationCenter defaultCenter] postNotificationName:@"NewPostsFetched" object:f];
然后冻结发生在createPostInFeed
:
// @synchronized(fetchRequest) { // THIS DOESN'T CHANGE ANYTHING // [moc.persistentStoreCoordinator lock]; // THIS NEITHER NSArray *fetchedItems; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *ent = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:moc]; fetchRequest.entity = ent; fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:@"title", @"url", @"feed.name", nil]; [fetchRequest setResultType:NSDictionaryResultType]; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"title == %@ AND url == %@ AND feed.rss == %@", title, url, feed.rss]; NSError *error = nil; fetchedItems = [moc executeFetchRequest:fetchRequest error:&error]; // FREEZES HERE // [moc.persistentStoreCoordinator unlock]; // THIS DOESN'T CHANGE ANYTHING // } // Synchronized neither...
更新(2):这是时间分析器看到的。
更新(3):编辑的块:
NSUInteger fetchedItems; NSString *feedRSS=feed.rss; NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *ent = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:moc]; fetchRequest.entity = ent; fetchRequest.predicate = [NSPredicate predicateWithFormat:@"title == %@ AND url == %@ AND feed.rss == %@", title, url, feedRSS]; NSLog(@"MainViewController::createPostInFeed> Before fetchRequest for %@ (%@)", title, url); NSError *error = nil; fetchedItems = [moc countForFetchRequest:fetchRequest error:&error]; NSLog(@"MainViewController::createPostInFeed> After fetchRequest for %@ (%@)", title, url); // THIS NSLOGGING NEVER HAPPENS
更新(4):调用树倒置的新分析器图片。
createPostInFeed
的目标是什么? 你表明你正在做一个抓取,但是你用这个抓取做什么? 这是一个“插入或更新”检查? 还是只是一个“插入或跳过”testing?
任何提取都将lockingNSPersistentStoreCoordinator
并导致您的应用程序在执行提取时可能locking。 有办法来减轻这一点:
- 运行仪器
- 让你的提取更有效率
- 如果你不需要对象(在插入或跳过testing),然后做一个计数
- 抓取背景队列,并确保您的主MOC具有所有需要避免locking的对象
你的乐器configuration文件显示给你什么?
createPostInFeed
做的是什么取得的结果?
- 如何在iOS 9.0 Beta中实现新的Core Data模型构build器的“独特”属性
- 聊天,会话,消息传递 – CoreData模型
- 如何在iOS 10 Swift 3中初始化NSFetchedResultsController
- 核心数据轻量级迁移在应用程序更新后崩溃
- CoreDataasynchronous获取导致并发debugging器错误
- 何时使用核心数据的NSMainQueueConcurrencyType?
- Swift + CoreData:无法在NSManagedObject子类上设置Bool – Bug?
- 我是否需要启用WAL模式将.SQLite从包复制到Document目录?
- 核心数据“无法find源存储模型”;