【问题标题】:CoreData concurrency and releasing objectsCoreData 并发和释放对象
【发布时间】:2016-07-12 08:56:28
【问题描述】:

我目前正在验证我们在多线程环境中使用的新 CoreData 架构。为了进行分析,我使用GDCoreDataConcurrencyDebugging 打印警告,每次从错误的线程/队列访问 ManagedObject(据我所知)。

现在我收到大量这样的警告:

Invalid concurrent access to managed object calling 'release'

我能够在生成警告的地方放置一个断点,代码如下所示:

-(MyObject*) createMyObject {
    return (MyObject*)[self insertNewObjectEntityWithName:@"MyObject"];
}

-(NSManagedObject*) insertNewObjectEntityWithName:(NSString*) entityName {
    __block NSManagedObject *managedObject;
    [self.managedObjectContext performBlockAndWait:^(void) {
        managedObject = [NSEntityDescription insertNewObjectForEntityForName:entityName
                                      inManagedObjectContext:self.managedObjectContext];
    }];
    return managedObject;
}

它在返回后打破了createMyObject-method,我猜这是在释放对象时。 CoreData-concurrency 和 object-release 有什么特别之处吗? 我环顾四周,没有提到任何关于对象释放的内容,只有关于我没有使用的自动释放池。

【问题讨论】:

    标签: ios objective-c multithreading core-data concurrency


    【解决方案1】:

    您正在通过performBlockAndWait: 调用执行工作,这是正确的。但是,您继续返回对象,可能来自不同的线程。那是不合法的。所有托管对象都必须从创建它们的线程/队列中访问,objectID 属性除外,该属性始终有效。

    【讨论】:

    • 感谢您的快速回复。所以基本上我不允许从我的执行块中给出任何对象?
    • 正确。通常的做法是使用从同一上下文中调用的完成块,或者传递objectIDs 并重新获取到不同的上下文中。
    • 哦,真可惜。我认为我们将不得不改造我们的很多软件架构。非常感谢
    【解决方案2】:

    请使用此代码获取 managedObjectContext 。托管对象必须从创建它们的线程/队列中访问。

     - (NSManagedObjectContext *)managedObjectContext
        {
            NSThread *thisThread = [NSThread currentThread];
            if (thisThread == [NSThread mainThread])
            {
    
                if (_managedObjectContext != nil) {
                    return _managedObjectContext;
                }
                //
                if ([self persistentStoreCoordinator] != nil) {
                    _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
                    [_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
                }
                [_managedObjectContext setRetainsRegisteredObjects:YES];
                [_managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
                return _managedObjectContext;
    
            }
            else
            {
                //Return separate MOC for each new thread
                NSManagedObjectContext *threadManagedObjectContext = [[thisThread threadDictionary] objectForKey:@"MOC_KEY"];
                if (threadManagedObjectContext == nil)
                {
                    threadManagedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
                    NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
                    [threadManagedObjectContext setPersistentStoreCoordinator: coordinator];
                    [[thisThread threadDictionary] setObject:threadManagedObjectContext forKey:@"MOC_KEY"];
    
                }
    
                return threadManagedObjectContext;
            }
        }
    

    【讨论】:

    • 我已经实现了类似的东西。这似乎不是这里的问题,而是@Avi 指出的架构误解。
    猜你喜欢
    • 2013-11-29
    • 2011-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-05
    • 1970-01-01
    相关资源
    最近更新 更多