__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
можете [error retain] така или иначе без проверка (!results) нали? разрешено ли е изпращането на съобщения до null? - 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
Бих си помислил, че изричното деклариране на резултатите като нула в началото би било по-безопасно. например __block NSArray *резултати = нула;. по този начин, ако 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