2017-08-01 57 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