Восстановите отношения NSManagedObject в фоновых потоках - PullRequest
2 голосов
/ 27 марта 2012

Я разрабатываю приложение с помощью Core Data, и мне нужно выполнить некоторые вычисления в фоновом потоке, чтобы создать XML-файл на основе определенных NSManagedObject.

Следуя документации, я настроил подкласс NSOperation. Этот класс имеет свойство, подобное следующему:

@property (nonatomic, retain) NSArray* objectIDs;

где objectIDs - массив идентификаторов управляемых объектов (типа NSManagedObjectID). Это необходимо в соответствии с документацией: NSManagedObject не являются потокобезопасными.

Внутри подкласса main из NSOperation я делаю следующее:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

NSManagedObjectContext *exportContext = [[NSManagedObjectContext alloc] init];
[exportContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];

for (NSManagedObjectID* objectID in self.orderObjectIDs) {

    NSError* error = nil;
    Order* order = (Order*)[exportContext existingObjectWithID:objectID error:&error];

    // order.someRelationship is fault here...

    // Create XML file here...
}

[exportContext reset];
[exportContext release], exportContext = nil;

[[NSNotificationCenter defaultCenter] postNotificationName:kRegisterComplete object:self];

[pool drain];
pool = nil;

Внутри цикла for я выбираю нужный объект, используя метод existingObjectWithID:error класса NSManagedObjectContext, начиная с

В отличие от objectWithID: этот метод никогда не возвращает ошибку.

Метод работает. Я могу получить свойства этого найденного объекта. Единственная проблема заключается в том, что отношения выбираются как ошибки.

Сказал, у меня два вопроса.

Во-первых, это правильный подход к fecth NSManagedObject в фоновом потоке? Затем, как я могу получить отношения для каждого выбранного объекта в цикле for? Нужно ли создавать NSFetchedRequest для извлечения объекта отношения на основе конкретного объекта, который был выбран через идентификатор?

Заранее спасибо.

Ответы [ 2 ]

2 голосов
/ 31 марта 2012

Почему тебя волнует, что отношения - это ошибка?Доступ к нему заполнит ошибку и вернет данные. Вас почему-то беспокоит дисковый ввод-вывод?

Вы можете попробовать использовать предварительную выборку, чтобы уменьшить некоторые издержки ввода-вывода, но его полезность ограниченаотношение к извлекаемой сущности:

https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/CoreDataFramework/Classes/NSFetchRequest_Class/NSFetchRequest.html

В этом случае вы создадите запрос на выборку с предикатом, например, так:

[NSPredicate predicateWithFormat:@"SELF == %@", objectID];

Это вернетдля вас только тот управляемый объект, который вы желаете, и с предварительной загрузкой отношений не будет ошибки.

Вы можете дополнительно оптимизировать это, используя предложение IN и извлекая все объекты сразу:

[NSPredicate predicateWithFormat:@"SELF IN (%@)", desiredObjectIDs];
0 голосов
/ 31 марта 2012

Вам необходимо убедиться в следующем:

  • Перед передачей любых идентификаторов объектов, которые вы делаете - [NSManagedObjectContext obtainPermanentIDsForObjects:error:] в исходном потоке.

(в основном потоке)

[managedObjectContext obtainPermanentIDsForObjects:objectIDs error:nil]
  • Прежде чем пытаться получить доступ к этим объектам из другого потока (включая их отношения), вам необходимо сохранить NSManagedObjectContext исходного потока. В противном случае объекты не будут существовать в постоянстве, и ваш фоновый поток не сможет получить его (или другие отношения). Самый простой способ убедиться в этом - вызвать блокировку сохранения в главном потоке в начале выполнения NSOperation. Например:

dispatch_sync(dispatch_get_main_queue(), { [managedObjectContext save:nil]; });

Вы можете сделать NSFetchRequest или получить доступ к отношениям напрямую, в зависимости от того, какой путь более удобен; вероятно, доступ к отношениям напрямую. Вам не нужно вызывать [NSManagedObjectContext reset] в конце вашей рутины.

...