Ios 多线程冲突核心数据

Ios 多线程冲突核心数据,ios,multithreading,core-data,magicalrecord,Ios,Multithreading,Core Data,Magicalrecord,我有一个应用程序,在启动时使用操作列表下载数据,由于未知的核心数据原因,它会随机崩溃,因此我花了几天时间检查使用MagicalRecord在多线程核心数据中更新/获取数据的最佳实践。其中一个选项是启用多线程调试器-com.apple.CoreData.concurrenceydebug 1,其中Xcode在违反应用程序规则时停止应用程序。因此,Xcode在这一行停止我的应用程序[SyncRequestEntity MR\u createEntityInContext:[self-getPriva

我有一个应用程序,在启动时使用操作列表下载数据,由于未知的核心数据原因,它会随机崩溃,因此我花了几天时间检查使用MagicalRecord在多线程核心数据中更新/获取数据的最佳实践。其中一个选项是启用多线程调试器
-com.apple.CoreData.concurrenceydebug 1
,其中Xcode在违反应用程序规则时停止应用程序。因此,Xcode在这一行停止我的应用程序
[SyncRequestEntity MR\u 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说我违反了多线程核心数据规则。有人知道发生了什么事吗

我们在开发自己的应用程序时也遇到了同样的问题

当您尝试在与上下文线程不同的线程中执行写操作时,它有时会崩溃

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

-(NSManagedObjectContext*)getPrivateManagedObjectContext
{
if(self.managedObjectContext!=nil){
返回self.managedObjectContext;
}
NSPersistentStoreCoordinator*coordinator=[self-getPersistentStoreCoordinator];
if(协调器!=nil){
self.managedObjectContext=[[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[self.managedObjectContext setPersistentStoreCoordinator:coordinator];
}
返回self.managedObjectContext;
}
然后,当需要执行任何操作时,应使用此方法确保块在上下文的同一线程上运行:

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

我们在开发自己的应用程序时也遇到了同样的问题

当您尝试在与上下文线程不同的线程中执行写操作时,它有时会崩溃

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

-(NSManagedObjectContext*)getPrivateManagedObjectContext
{
if(self.managedObjectContext!=nil){
返回self.managedObjectContext;
}
NSPersistentStoreCoordinator*coordinator=[self-getPersistentStoreCoordinator];
if(协调器!=nil){
self.managedObjectContext=[[NSManagedObjectContext alloc]initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[self.managedObjectContext setPersistentStoreCoordinator:coordinator];
}
返回self.managedObjectContext;
}
然后,当需要执行任何操作时,应使用此方法确保块在上下文的同一线程上运行:

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


MR\u上下文的代码是什么?您是否考虑到块可以在不同的线程上运行?添加细节@AminNegm Awad。我这里没有使用任何块。您使用的是哪个版本的MagicalRecord?@casademora,正如您在上面更新的代码中所看到的,它是2.3。MR_context的代码是什么?您是否考虑到块可以在不同的线程上运行?添加细节@AminNegm Awad。我没有在这里使用任何块。您使用的是哪个版本的MagicalRecord?@casademora,正如您在上面更新的代码中看到的,它是2.3。为什么我需要使用performBlock?我已经处于后台线程(NSOperation)中,我只想使用我为每个操作创建的privateContext创建/获取/插入实体,但似乎我违反了他们的一条规则,到目前为止我还不了解。问题是,如果同时执行写操作,它可能会崩溃。您只需要使用一个私有上下文,并在同一个上下文线程中执行每个操作。拥有一个全局私有上下文和每个线程拥有私有上下文之间的区别是什么?在我看来,我会得到同样的结果,对吗?主要问题是所有操作都应该在performBlock或performBlockAndWait中。只有一个线程,将确保所有线程都使用相同的“线程队列”。我尝试为所有线程只使用一个私有上下文,但得到了相同的结果。为什么我需要使用performBlock?我已经处于后台线程(NSOperation)中,我只想使用我为每个操作创建的privateContext创建/获取/插入实体,但似乎我违反了他们的一条规则,到目前为止我还不了解。问题是,如果同时执行写操作,它可能会崩溃。您只需要使用一个私有上下文,并在同一个上下文线程中执行每个操作。拥有一个全局私有上下文和每个线程拥有私有上下文之间的区别是什么?在我看来,我会得到同样的结果,对吗?主要问题是所有操作都应该在performBlock或performBlockAndWait中。如果只有一个线程,将确保所有线程都使用相同的“线程队列”。我尝试为所有线程只使用一个私有上下文,但得到了相同的结果。。