1

我已啓用com.apple.CoreData.ConcurrencyDebug 1檢查Core Data併發錯誤。我有一個Swift類下面的代碼片段:非法訪問主線程中的託管對象上下文,爲什麼?

lazy var context: NSManagedObjectContext! = { 
    var appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate 
    return appDelegate.managedObjectContext! 
}() 

func getAllEntitiesToRootContext() -> [MyEntity]? { 
    let fetchRequest = NSFetchRequest(entityName:"MyEntity") 

    do { 
     let fetchedResults = try context.executeFetchRequest(fetchRequest) as! [MyEntity] 

     if fetchedResults.count > 0 { 
      return fetchedResults 
     } else { 
      return nil 
     } 
    } catch let error as NSError { 
     print("could not fetch \(error), \(error.userInfo)") 
     return nil 
    } 
} 

如果我理解正確的話,我從AppDelegate獲取上下文關聯到主線程,對不對?

不過,從另一個Objective-C類我有,我做的:

self.myEntitiesArray = [mySwiftClass getAllEntitiesToRootContext]; 

,我得到這個錯誤日誌:

CoreData: error: The current thread is not the recognized owner of this NSManagedObjectContext(0x1a25f8a0). Illegal access during executeFetchRequest:error:

我不明白爲什麼......我應該有這樣的背景相關的主線程,我打電話getAllEntitiesToRootContext從主線程...

請我需要幫助。在此先感謝

編輯:這些都是AppDelegate有關Core Data方法:

- (NSManagedObjectContext *)managedObjectContext 
{ 
    // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 
    if (_managedObjectContext != nil) { 
     return _managedObjectContext; 
    } 

    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 
    if (!coordinator) { 
     return nil; 
    } 
    _managedObjectContext = [[NSManagedObjectContext alloc] init]; 
    [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 
    return _managedObjectContext; 
} 

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator 
{ 
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 
    if (_persistentStoreCoordinator != nil) { 
     return _persistentStoreCoordinator; 
    } 

    // Create the coordinator and store 

    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"MyApp.sqlite"]; 
    NSError *error = nil; 
    NSString *failureReason = @"There was an error creating or loading the application's saved data."; 
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 
     // Report any error we got. 
     NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 
     dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 
     dict[NSLocalizedFailureReasonErrorKey] = failureReason; 
     dict[NSUnderlyingErrorKey] = error; 
     error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 
     // Replace this with code to handle the error appropriately. 
     // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 
     NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 
     abort(); 
    } 

    return _persistentStoreCoordinator; 
} 

- (NSManagedObjectModel *)managedObjectModel 
{ 
    // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 
    if (_managedObjectModel != nil) { 
     return _managedObjectModel; 
    } 
    NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"MyApp" withExtension:@"momd"]; 
    _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 
return _managedObjectModel; 
} 

編輯2:我使用Xcode 7和測試iOS 9設備。

編輯3:如果我禁用com.apple.CoreData.ConcurrencyDebug 1,我從getAllEntitiesToRootContext()對象......我真的不明白什麼,爲什麼會出現這種情況?

編輯4:我做了一些測試。如果我這樣做從01​​類:

- (void)getEntities 
{ 
    AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; 
    NSManagedObjectContext *mainContext = appDelegate.managedObjectContext; 

    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"MyEntity"]; 
    NSArray *entities = [mainContext executeFetchRequest:fetchRequest error:nil]; 

    for (NSManagedObject *item in entities) { 
     NSLog(@"Name: %@", ((MyEntity *)item).name); 
    } 
} 

我打電話executeFetchRequest和實體的名稱在日誌控制檯中顯示時,有時會沒有錯誤。其他時候,我也得到類似的核心數據錯誤,我上面貼了一個,我也得這樣做的時候,因爲我是這樣做的:

- (NSArray *)getEntities 
{ 
    MyEntityDao *myEntityDao = [[MyEntityDao alloc] init]; 
    self.myEntities = [[myEntityDao getAllEntitiesToRootContext] mutableCopy]; 

    return [[NSArray arrayWithArray:self.myEntities] copy]; 
} 

其中MyEntityDaoSwift類,定義lazy var contextgetAllEntitiesToRootContext(),我得到的核心數據錯誤我也張貼在上面...爲什麼?這兩個代碼片段是否相同?爲什麼我有時會說主線程不是我從AppDelegate檢索到的MOC的所有者?

我真的需要這方面的幫助...

+0

如何初始化'appDelegate.managedObjectContext'? – Leo

+0

@Leo我從'AppDelegate'默認提供的方法得到它# – AppsDev

+0

@Leo我編輯了我的問題 – AppsDev

回答

1

似乎調用getAllEntitiesToRootContext(),在某些情況下,我檢索從隊列中,這不是主線程,是什麼原因導致這種情況下,以在其他隊列進行初始化在AppDelegate定義的背景下...

我感謝Leo的評論以及Marcus S. Zarra的回答,謝謝。

+2

從[iOS 9]開始,[[NSManagedObjectContext alloc] init]'已棄用。切換到正確的初始化程序,這將對此類問題有很大的幫助。保持打開調試標誌。很高興你把它整理出來。 –

2

是什麼context.executeFetchRequest(fetchRequest)辦?代碼是什麼樣的?

在某些時候,您處於主隊列以外的另一個隊列中。

您正在收到的錯誤表明您違反了線程限制。如果你在Xcode中有異常和錯誤的斷點,它會向你顯示違反規則的確切代碼行以及它被執行的隊列。

Xcode停止工作的代碼行是什麼?

當Xcode停止時,你在什麼隊列?

我不會推薦關掉那個調試標誌,它可以幫助你,讓你發現線程錯誤。關閉它只是隱藏了問題,並會導致用戶數據在生產中出現問題。更好地投入時間,瞭解正在發生的事情並正確糾正。

+0

非常感謝,我要測試一些事情,並試圖看看發生了什麼......我想我誤解了一些「核心數據」基礎知識,這就是爲什麼我在整個應用程序中錯誤地管理它,這是我第一次不直接管理SQlite文件,我的數據模型和應用程序邏輯比我發現的例子要複雜一些。我將寫另一篇文章來澄清一些想法。 – AppsDev

+0

我無法理解這種情況下發生了什麼......我的'lazy var context'在主線程中被調用,並且它檢索在AppDelegate中定義的MOC,並且這樣的MOC應該屬於main線程,對嗎?但是當我嘗試從'getAllEntitiesToRootContext'中嘗試獲取調用'executeFetchRequest'的數據時,我得到了我在問題中提到的Core Data錯誤...可能是因爲我試圖獲取的數據是從私有MOC中保存的?它有意義嗎? – AppsDev

+0

我再次編輯我的問題。 – AppsDev

相關問題