我有一个saveMOC
,它是mainMOC
的直接父级,我需要在线获取另一个tmpMOC
,以便在从大量记录中获取大量记录时阻止我的用户界面互联网。
我的应用冻结了。 我可以将它缩小到这一点:
fetchedItems = [tmpMOC executeFetchRequest:fetchRequest error:&error];
我尝试将其括在dispatch_sync
,[moc.parentcontext.parentcontext.persistentStoreCoordinator lock/unlock]
,[whatevermoc performBlockAndWait]
...
我也尝试获取_mainMOC
......没办法......
我理解executeFetchRequest
不是线程安全的,所以,我如何锁定我需要锁定的东西以确保我没有插入双?
有人可以帮忙吗?
更新(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中创建 temporaryMOC
:
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): 这是Time Profiler看到的内容。
更新(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): 与呼叫树倒置的新的探查器pic。
答案 0 :(得分:3)
createPostInFeed
的目标是什么?你表明你正在进行一次获取,但你对该获取做了什么?这是“插入或更新”检查吗?或者它只是一个“插入或跳过”测试?
任何提取都会锁定NSPersistentStoreCoordinator
并导致应用程序在执行提取时可能锁定。有办法缓解这个问题:
您的乐器资料会显示给您什么?
createPostInFeed
对该抓取的结果做了什么?