2017-08-01 87 views
0

在使用NSSortDescriptor对各种属性进行排序后,我想捕获排序顺序并将其保存回核心数据。为了保持uX稳定,我试图在后台使用单独的MOC来完成此操作。但是,我遇到枚举错误时发生了变异,可能是因为其他一些事情正在进行 - 包括与服务器同步并且FRC进行提取。IOS/Objective-C:后台保存到NSFetchedResultsController后的核心数据

任何人都可以看到什么可能是我的代码错了吗?在此先感谢您的任何建议。

-(NSFetchedResultsController *)fetchedResultsController { 

//code to carry out fetch 
//Sort order specified according to parameters 

_theItems =[_fetchedResultsController fetchedObjects]; 
//at this point fetch should be complete 
NSManagedObjectContext *mainMOC = _managedObjectContext; 
    NSManagedObjectContext*privateContext =[[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
    [privateContext setParentContext:mainMOC]; 
    [privateContext performBlock:^{ 

     for (int i = 0; i < _theItems.count; i++) 
     { 
      Items* oneitem = theItems[i]; 
      oneitem.sortorder = i; 
     } 

     NSError *error = nil; 
     if (![privateContext save:&error]) { 
      NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
      abort(); 
     } 
     [mainMOC performBlockAndWait:^{ 
      NSError *error = nil; 
      if (![mainMOC save:&error]) { 
       NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
       //abort(); 
      } 
      else { 
       _managedObjectContext = mainMOC; 
      } 
     }]; 
    }]; 
    mainMOC=nil; 
    privateContext = nil; 

return _fectchedResultsController; 
} 

编辑:

从苹果文档:

NSArray *jsonArray = …; //JSON data to be imported into Core Data 
NSManagedObjectContext *moc = …; //Our primary context on the main queue 

NSManagedObjectContext *private = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; 
[private setParentContext:moc]; 

[private performBlock:^{ 
    for (NSDictionary *jsonObject in jsonArray) { 
     NSManagedObject *mo = …; //Managed object that matches the incoming JSON structure 
     //update MO with data from the dictionary 
    } 
    NSError *error = nil; 
    if (![private save:&error]) { 
     NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
     abort(); 
    } 
    [moc performBlockAndWait:^{ 
     NSError *error = nil; 
     if (![moc save:&error]) { 
      NSLog(@"Error saving context: %@\n%@", [error localizedDescription], [error userInfo]); 
      abort(); 
     } 
    }]; 
}]; 

编辑2:

放置在viewdidappear代码停止除外。另外,我将代码更改为以下版本,并且“似乎”正常工作。这是现在线程安全吗?

for (int i = 0; i < _theItems.count; i++) 
      { 
      Items* oneitem = theItems[i]; 
      NSManagedObjectID* oneID = oneitem.objectID; 
      Items *myItem = [privateContext objectWithID:oneID]; 
      myItem.sortorder = i; 

      } 
+1

恐怕这里有些事情是非常错误的。看起来你已经建立了一个私有上下文,然后遍历一组对象(可能是ManagedObject的子类),它们来自哪里?您没有在该方法的任何变体上使用objectWithID检索任何对象,因此您可能正在操纵最初从主上下文中检索到的对象(并在performBlock调用中执行该操作,因此在私有上下文线程 - ouch!上执行该操作)。然后,在错误的线程中操作了来自另一个上下文的对象,您可以尝试保存私有上下文,认为它可以工作。不。 – TheBasicMind

+0

我也读过托管对象不是线程安全的,但对象标识符是这样的,因此您需要使用objectwithID检索所有托管对象。但是,我也读过NSPrivateQueueConcurrencyType似乎已经简化了这个过程,现在可以完成上述操作。也许我误解了。将尝试找到参考。 – user6631314

+0

这是我在文档中阅读:https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/CoreData/Concurrency.html – user6631314

回答

0

您无法从多个上下文访问NSManagedObjects。假设[NSFetchedResultsController fetchedObjects]返回_managedObjectContext拥有的对象,则不能从privateContext访问它们。

一个选项可能是将NSManagedObjectIDs传递给私有MOC并使用该ID来查询相应对象的主MOC。

这有道理吗?

+0

是FRC自动管理对象中的获取对象吗? – user6631314

+0

是的。从[文档](https://developer.apple.com/documentation/coredata/nsfetchedresultscontroller/1622278-fetchedobjects?language=objc):_“results数组反映了控制器管理对象中托管对象的内存中状态上下文“_ – kevdoran

+0

当我将代码移动到viewdidload时,错误不再出现。我确实需要FRC的临时订单,NSArray * theItems或在这种情况下_theItems。你能建议使用objectforid的代码吗?我想它会在循环中,因为我抓取数组中的每个sortOrder。 – user6631314