У меня есть приложение, в котором я загружаю данные при запуске, используя список операций, и он случайно разбивается по неизвестным причинам основных данных, поэтому я потратил несколько дней на проверку лучших практик по обновлению/извлечению данных в многопоточном ядре данные с MagicalRecord. Один из вариантов состоял в том, чтобы включить многопоточный отладчик -com.apple.CoreData.ConcurrencyDebug 1
, где Xcode останавливает приложения, когда он нарушает одно из своих правил. Таким образом, Xcode останавливает мое приложение на этой линии [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 говорит, что я нарушаю правила обработки данных с несколькими потоками. Кто-нибудь знает, что происходит?
Что такое код из 'MR_context'? Вы принимали во внимание, что блоки могут работать на разных потоках? –
Добавления деталей @ AminNegm-Awad. Я не использую блок здесь. – Maystro
Какую версию MagicalRecord вы используете? – casademora