Переменные __block должны быть сохранены в блоке

Я хочу использовать массив результатов после выполнения блока, мой вопрос: следует ли сохранять экземпляр массива результатов, поскольку он был создан из блока?

__block NSError *error = nil;    
__block NSArray *results;

[moc performBlockAndWait:^(void) {        
    results = [moc executeFetchRequest:fetchRequest error:&error]; 
    [results retain];
}];
if(results){
   //Do somehting
}

person the Reverend    schedule 18.10.2011    source источник
comment
executeFetchRequest:error: возвращает автоматически выпущенный массив? Я предполагаю, что так и должно быть, и поэтому вы должны сохранить его.   -  person Jessedc    schedule 18.10.2011
comment
Если вы извлекаете NSManagedObjects (или подклассы), то это не сработает, и вместо этого вы должны выполнять всю свою обработку в -performBlockAndWait:.   -  person hypercrypt    schedule 19.10.2011


Ответы (3)


Чтобы быть педантично правильным, вы должны сделать что-то вроде:

__block NSError *error = nil;    
__block NSArray *results;

[moc performBlockAndWait:^(void) {        
    results = [moc executeFetchRequest:fetchRequest error:&error]; 
    [results retain];
    if (!results) [error retain];
}];

if(results){
   //Do somehting
   [results release]; // or not -- assign it to something
} else {
   // Do something with error
   [error release]; // or autorelease
}

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

Всеобъемлющее правило касается передачи потоков; вы передаете объекты из одного потока выполнения (где бы ни выполнялся блок) в вызывающий поток. При передаче права собственности должно быть жесткое удержание.

person bbum    schedule 18.10.2011
comment
Со значительно большим количеством деталей, да... по крайней мере, это будет одна из интерпретаций того, что вы сказали. Другой был бы неправ. ;) Документация по этому вопросу... отсутствует... зарегистрирована ошибка. - person bbum; 18.10.2011
comment
вы можете [сохранить ошибку] ​​в любом случае, не проверяя (! результаты), верно? обмен сообщениями с нулевым значением разрешен? - person the Reverend; 18.10.2011
comment
В этом случае значение error будет неопределенным, если только results не равно нулю. - person bbum; 19.10.2011
comment
но если вы инициализируете ошибку до нуля, разве она не должна быть нулевой, если не установлена ​​выборкой? - person the Reverend; 19.10.2011
comment
Нет — нет никакой гарантии, что executeFetchRequest:error: не установит *error (внутренне) какое-то случайное значение. error действителен только в том случае, если возвращаемое значение указывает на наличие ошибки. - person bbum; 19.10.2011
comment
я бы подумал, что явное объявление результатов как nil в начале было бы безопаснее. например __block NSArray *results = nil;. таким образом, если PerformBlockAndWait не вызывает ваш обработчик, вы не имеете дело с результатами, содержащими то, что было в стеке, когда вы вводили свой метод. - person unsynchronized; 23.08.2012
comment
Переменные __block не будут работать, если компилятор не инициализирует их значением 0. - person bbum; 23.08.2012

Я думаю, что это подпадает под общее правило владения для управления памятью obj-c. Если вам нужен этот массив, вы должны заявить право собственности, сохранив его и освободив, когда закончите.

person D.C.    schedule 18.10.2011

Если вы получаете автоматически выпущенный объект, он обычно остается действительным до конца текущего вызова метода и даже может быть возвращен как результат метода. Если вам нужно сохранить его для будущего использования, вы должны сохранить его.

person Parag Bafna    schedule 18.10.2011
comment
Типа, проблема, однако, в том, что это объект в блоке, и этот блок, хотя и выполняется синхронно, не обязательно находится в одном и том же потоке. - person bbum; 18.10.2011
comment
Этот. Небезопасно предполагать, что автоматически выпущенный объект будет в любое время в многопоточной среде. - person D.C.; 18.10.2011