多线程违反核心数据 [英] Multithreading violation core data

查看:491
本文介绍了多线程违反核心数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个应用程序,我在启动时使用操作列表下载数据,它随机崩溃的未知核心数据的原因,所以我花了几天时间检查最佳做法更新/获取数据在多线程核心数据与MagicalRecord。其中一个选项是启用多线程调试器 -com.apple.CoreData.ConcurrencyDebug 1 其中Xcode停止的应用程序,当它违反了其中的一个规则。所以,Xcode在此行上停止我的应用程序 [SyncRequestEntity MR_createEntityInContext:[self getPrivateContext]]

I have an app where I download the data on startup using a list of operations and it crashes randomly for unknown core data reasons so I spent few days on checking the best practices to update/fetch data in multithreading core data with MagicalRecord. One of the options was to enable the multithreading debugger -com.apple.CoreData.ConcurrencyDebug 1 where Xcode stops the apps when it violates one of their rules. So, Xcode stops my app on this line [SyncRequestEntity MR_createEntityInContext:[self getPrivateContext]]

+ (MagicalRecordVersionNumber) version
{
    return MagicalRecordVersionNumber2_3;
}
@implementation NSManagedObjectContext (MagicalRecord) 

+ (NSManagedObjectContext *) MR_context
{
    return [self MR_contextWithParent:[self MR_rootSavingContext]];
}

+ (NSManagedObjectContext *) MR_contextWithParent:(NSManagedObjectContext *)parentContext
{
    NSManagedObjectContext *context = [self MR_newPrivateQueueContext];
    [context setParentContext:parentContext];
    [context MR_obtainPermanentIDsBeforeSaving];
    return context;
}

- (void) MR_obtainPermanentIDsBeforeSaving
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(MR_contextWillSave:)
                                                     name:NSManagedObjectContextWillSaveNotification
                                                   object:self];
}
+ (NSManagedObjectContext *) MR_newPrivateQueueContext
{
    NSManagedObjectContext *context = [[self alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
    MRLogInfo(@"Created new private queue context: %@", context);
    return context;
}

@end

@implementation MyClass

    - (NSManagedObjectContext *) getPrivateContext
    {
        if (self.privateContext == nil)
        {
            self.privateContext = [NSManagedObjectContext MR_context];
        }
        return self.privateContext;
    }

    - (SyncRequestEntity *) getSyncRequest
    {
        SyncRequestEntity *syncRequest = [SyncRequestEntity MR_findFirstByAttribute:@"key" withValue:self.itemKey inContext:[self getPrivateContext]];

        // Checking if the entity was sync previously with the same filters.
        if (syncRequest == nil)
        {
            syncRequest = [SyncRequestEntity MR_createEntityInContext:    [self getPrivateContext]];
        }

        return syncRequest;
    }
@end

@implementation NSManagedObject (MagicalRecord)
+ (id) MR_createEntityInContext:(NSManagedObjectContext *)context
{
    if ([self respondsToSelector:@selector(insertInManagedObjectContext:)] && context != nil)
    {
        id entity = [self performSelector:@selector(insertInManagedObjectContext:) withObject:context];
        return entity;
    }
    else
    {
        NSEntityDescription *entity = nil;
        if (context == nil)
        {
            entity = [self MR_entityDescription];
        }
        else
        {
            entity  = [self MR_entityDescriptionInContext:context];
        }

        if (entity == nil)
        {
            return nil;
        }

        return [[self alloc] initWithEntity:entity insertIntoManagedObjectContext:context];
    }
}
@end

privateContext 是每个操作的局部变量,因此我有每个操作的私有上下文,以便不中断主操作。关键是我为每个线程创建一个私有上下文,我只是试图使用这个上下文创建一个新的 NSManagedObject 实例,Xcode说我违反了多线程核心数据规则。有谁有任何线索的发生?

The privateContext is a local variable for each operation so I have private contexts for each operation in order to not interrupt the main one. The point is that I create one private context for each thread and I'm just trying to create a new NSManagedObject instance using this context and Xcode says that I'm violating the multithreading core data rules. Does anyone have any clue on what's happening?

推荐答案

我们在开发自己的应用时遇到同样的问题。

We have the same issue when developing our own app.

我们的解决方案是在<$ c上创建一个私有管理器$ c> AppDelegate.m 文件。只需添加以下代码:

Our solution was to make a private manager on the AppDelegate.m file. Just add this code:

- (NSManagedObjectContext *)getPrivateManagedObjectContext
{
    if (self.managedObjectContext != nil) {
        return self.managedObjectContext;
    }

    NSPersistentStoreCoordinator *coordinator = [self getPersistentStoreCoordinator];
    if (coordinator != nil) {
        self.managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [self.managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    return self.managedObjectContext;
}

然后当您需要执行任何操作时,该块在上下文的同一个线程上运行:

Then when you need to perform any operation, you should use this method that ensures the block is running on the same thread of the context:

[self.managedObjectContext performBlock:^{...}];
[self.managedObjectContext performBlockAndWait:^{...}];

这篇关于多线程违反核心数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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