在主线程中非法访问受管对象上下文,为什么? [英] Illegal access to managed object context in main thread, why?

查看:181
本文介绍了在主线程中非法访问受管对象上下文,为什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已启用 com.apple.CoreData.ConcurrencyDebug 1 以检查 Core Data 并发错误。我在 Swift 类中有以下代码片段:

I've enabled com.apple.CoreData.ConcurrencyDebug 1 to check Core Data concurrency errors. I have the following code snippet in a Swift class:

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 获得的上下文与主线程相关联,是吗?

If I've correctly understood, the context I get from AppDelegate is associated to main thread, right?

但是,从另一个 Objective-C 类,我有:

But then, from another Objective-C class I have, I do:

self.myEntitiesArray = [mySwiftClass getAllEntitiesToRootContext];

我收到此错误日志:

CoreData:错误:当前线程不是此NSManagedObjectContext(0x1a25f8a0)的已识别所有者。 executeFetchRequest中的非法访问:错误:

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

我不明白为什么...我应该有这样的上下文关联到main线程,我从主线程调用 getAllEntitiesToRootContext ...

I don't understand why... I'm supposed to have such context associated to main thread, and I'm calling getAllEntitiesToRootContext from main thread...

请我需要帮助。提前感谢

Please I need help. Thanks in advance

EDIT:这些是与 Core Data code> AppDelegate :

These are the methods related to Core Data in AppDelegate:

- (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;
}

EDIT 2: c $ c> Xcode 7 并在 iOS 9 设备中进行测试。

EDIT 2: I'm using Xcode 7 and testing in iOS 9 device.

EDIT 3:如果我禁用 com.apple.CoreData.ConcurrencyDebug 1 ,我从 getAllEntitiesToRootContext $ c> ...我真的不明白什么,为什么会发生这种情况?

EDIT 3: If I disable com.apple.CoreData.ConcurrencyDebug 1, I get objects from getAllEntitiesToRootContext()... I don't really understand anything, why is this happening?

编辑4: 。如果我从 Objective-C 类中执行此操作:

EDIT 4: I've made some tests. If I do this from an Objective-C class:

- (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);
   }
}

我有时在调用<$ c $时没有错误c> executeFetchRequest ,并且日志控制台中显示实体的名称。其他时候,我也得到Core Data的错误类似于我上面发布的,我也得到当我做的时候:

I sometimes get no error when calling executeFetchRequest and the name of the entities is shown in logs console. Other times I also get the Core Data error similar that the one I posted above and I also get when doing as I was doing:

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

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

其中 MyEntityDao 定义 lazy var context 的getAllEntitiesToRootContext() >,我得到核心数据错误我也贴在上面...为什么?这两个代码段不等同吗?为什么我有时说主线程不是从 AppDelegate ?检索的MOC的所有者

where MyEntityDao is the Swift class that defines lazy var context and getAllEntitiesToRootContext(), I get the Core Data error I also posted above... why? Are not these two code snippets equivalent? Why I'm sometimes said that main thread is not the owner of the MOC I retrieve from AppDelegate?

真的需要帮助...

推荐答案

看起来在调用 getAllEntitiesToRootContext c $ c>,在某些情况下,我从一个不是主线程的队列中检索 AppDelegate 中定义的上下文,是什么原因导致该上下文被初始化其他队列...

It seems that before calling getAllEntitiesToRootContext(), in certain scenario I was retrieving the context defined in AppDelegate from a queue that wasn't the main thread, what was causing that context to be initialized in that other queue...

我发现这要感谢Leo的评论和Marcus S. Zarra的回答,谢谢。

I found this thanks to the comment of Leo and the answer of Marcus S. Zarra, thanks.

这篇关于在主线程中非法访问受管对象上下文,为什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆