本文介绍了Core-Data executeFetchRequest在后台线程中冻结应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我有一个 saveMOC 这是一个 mainMOC 的直接父,我需要在线获取另一个 tmpMOC ,以便在从互联网获取大量记录时不会阻止我的用户界面。 我的应用程序冻结。 我可以缩小到这一点: fetchedItems = [tmpMOC executeFetchRequest:fetchRequest error:& error] ; 我试图将它包含在 dispatch_sync [moc.parentcontext.parentcontext.persistentStoreCoordinator lock / unlock] , [whatevermoc performBlockAndWait] ... 我也尝试获取 _mainMOC ...没有办法... 我知道 executeFetchRequest 不是线程安全的,所以,如何锁定任何我需要锁定,以确保我没有插入一个双? 任何人都可以帮助? UPDATE(1) _saveMOC 在AppDelegate中实例化: - (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]; temporaryMOC 在MainViewController中创建 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] %d Posts ... / OK,(int)[feedItems count]); feed.valid = [NSNumber numberWithBool:YES]; for(RSItemtem * 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:@NewPostsFetchedobject:f];然后冻结发生在 createPostInFeed : $ // @synchronized(fetchRequest){//这不会改变任何值 // [moc.persistentStoreCoordinator lock ]; // this NEITHER NSArray * fetchedItems; NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription * ent = [NSEntityDescription entityForName:@PostinManagedObjectContext:moc]; fetchRequest.entity = ent; fetchRequest.propertiesToFetch = [NSArray arrayWithObjects:@title,@url,@feed.name,nil]; [fetchRequest setResultype: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]; //这不改变任何值 //} //同步既不... 更新(2): 这是Time Profiler看到的内容。 Update(3): 块编辑: NSUInteger fetchedItems; NSString * feedRSS = feed.rss; NSFetchRequest * fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription * ent = [NSEntityDescription entityForName:@PostinManagedObjectContext:moc]; fetchRequest.entity = ent; fetchRequest.predicate = [NSPredicate predicateWithFormat:@title ==%@ AND url ==%@ AND feed.rss ==%@,title,url,feedRSS]; NSLog(@MainViewController :: createPostInFeed> Before for 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): 与调用树反转的新的profiler pic。 解决方案您的目标是什么? createPostInFeed ?您显示您正在进行抓取,但是您对抓取做了什么?这是一个插入或更新检查? 任何获取将锁定 NSPersistentStoreCoordinator ,并导致您的应用程序可能会在执行提取时锁定 。有办法减轻这种情况: 运行乐器 > 如果您不需要对象(在插入或跳过测试中),请执行计数 在后台队列上获取并确保您的主MOC 您的乐器配置文件向您显示了什么? createPostInFeed 对该提取的结果有什么作用? I have a saveMOC which is the direct parent of a mainMOC, and I need for online fetch another tmpMOC in order not to block my UI whilst fetching a ton of records from the Internet.My app freezes.I could narrow it to this very point: fetchedItems = [tmpMOC executeFetchRequest:fetchRequest error:&error];I tried to enclose this within dispatch_sync, [moc.parentcontext.parentcontext.persistentStoreCoordinator lock/unlock], [whatevermoc performBlockAndWait]...I also try to fetch the _mainMOC... No way...I understand that executeFetchRequestis not thread safe, so, how do I lock whatever I need to lock to get sure I am not inserting a double?Anybody could help?UPDATE (1)_saveMOC instantiation in AppDelegate:- (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];temporaryMOCcreation in MainViewController: 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];Then the freeze happens in 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...Update (2):Here's what the Time Profiler sees.Update (3):Block edited: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 HAPPENSUpdate (4):New profiler pic with call tree inverted. 解决方案 What is your goal with createPostInFeed? You show that you are doing a fetch but what do you do with that fetch? Is this a "insert or update" check? or is it just a "insert or skip" test?Any fetch is going to lock the NSPersistentStoreCoordinator and cause your application to potentially lock up while the fetch is being performed. There are ways to mitigate that:Run InstrumentsMake your fetches more efficientIf you don't need objects (in a insert or skip test) then do a count insteadFetch on a background queue and make sure your main MOC has all the objects it needs to avoid a lockWhat does your instruments profile show you?What does createPostInFeed do with the results of that fetch? 这篇关于Core-Data executeFetchRequest在后台线程中冻结应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
08-14 13:19