Использование переменной в двух блоках - PullRequest
0 голосов
/ 12 января 2011

Я добавил метод -dct_asynchronousTaskWithWorkBlock:completionBlock: в NSManagedObjectContext, который запускает рабочий блок в другой очереди GCD, а затем запускает блок завершения в основном потоке. Метод выполняет следующие действия:

  1. Создает второй контекст управляемого объекта для использования в другой очереди
  2. Вызывает рабочий блок с этим новым контекстом
  3. Сохраняет и объединяет этот контекст в себя
  4. Вызывает блок завершения с собой

Это дополнение можно увидеть на GitHub .

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

__block NSManagedObjectID *objectID = nil;

[self.managedObjectContext dct_asynchronousTaskWithWorkBlock:^(NSManagedObjectContext *moc) {

    NSManagedObject *user = // create new user.

    objectID = [user objectID];

} completionBlock:^(NSManagedObjectContext *moc) {

    NSManagedObject *user = [moc objectWithID:objectID];

}];

Я также попытался скопировать блоки, и в обоих случаях я получаю EXC_BAD_ACCESS для objectID в блоке завершения.

Можно ли ссылаться на objectID пользователя в рабочем блоке из блока завершения? Или мне нужно работать так, чтобы обрабатывать передачу ссылки в методе category.

Обновление:

Люк был прав насчет сохранения вызовов через блок, поскольку пользователь в первом находится в фоновом потоке, а пользователь во втором - в основном.

Это мое исправление на данный момент:

__block NSManagedObjectID *objectID = nil;

[self.managedObjectContext dct_asynchronousTaskWithWorkBlock:^(NSManagedObjectContext *moc) {

    NSManagedObject *user = // create new user.

    objectID = [user objectID];
    [objectID retain];

} completionBlock:^(NSManagedObjectContext *moc) {

    NSManagedObject *user = [moc objectWithID:objectID];
    [objectID release];

}];

Теперь мне интересно, выглядит ли это странно. После прочтения только этого кода вы можете спросить, может ли быть утечка, например. Я знаю, что категория определенно вызывает блок завершения независимо от того, что происходит в первом блоке, но я не знаю, выглядит ли это достаточно очевидно только из этого фрагмента кода.

Ответы [ 2 ]

2 голосов
/ 12 января 2011

Люк прав, но ...

Почему вообще есть рабочий блок и блок завершения?

API GCD изначально выглядели так:* Но это оказалось глупо.WorkBlock всегда знает, когда он завершен, так почему бы не поместить логику завершения в workBlock?Помимо создания более простого API, он также устраняет необходимость иметь простой механизм для передачи состояния из рабочего блока в блок завершения.

dispatch_async(q, ^{
    ... do heavy duty work on background here ...
    dispatch_async(mainQueue, ^{
        ... merge into main queue context here ...
        ... update UI ...
    });
});
1 голос
/ 13 января 2011

Если цель вашей категории состоит в том, чтобы в ваших блоках работы и завершения не было кода, связанного с настройкой и демонтажем второго MOC, вы можете вернуть блок завершения из рабочего блока:

[self.managedObjectContext dct_asynchronousTask:^(NSManagedObjectContext *moc) {

    NSManagedObject *backgroundThreadUser = // create new user.
    NSManagedObjectID *objectID = [backgroundThreadUser objectID];

    return ^(NSManagedObjectContext *moc) {
        NSManagedObject *mainThreadUser = [moc objectWithID:objectID];
        // ...
    };
}];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...