多线程违反核心数据 [英] Multithreading violation core data
问题描述
我有一个应用程序,我在启动时使用操作列表下载数据,它随机崩溃的未知核心数据的原因,所以我花了几天时间检查最佳做法更新/获取数据在多线程核心数据与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屋!