Как передать право собственности из @autoreleasepool с ARC - PullRequest
4 голосов
/ 17 января 2012

У меня есть следующий код

- (NSString *)stringByEscapingXMLEntities;
{   
    NSString *result;
    @autoreleasepool {
        result = [self stringByReplacingOccurrencesOfString:@"&" withString:@"&"];
        result = [result stringByReplacingOccurrencesOfString:@"\"" withString:@"""];
        // ... lot of -stringByReplacingOccurrencesOfString: calls
        result = [result stringByReplacingOccurrencesOfString:@" " withString:@" "];
    }
    return result;
}

Теперь я спрашиваю себя, как бы передать право собственности result из метода.До ARC я бы сохранил result перед выходом из блока автоматического выпуска и вернул его автоматически освобожденным в конце метода.

Спасибо!

Ответы [ 4 ]

4 голосов
/ 17 января 2012

Для этого есть два способа:

  • Переименовать метод в что-то вроде copyStringByEscapingXMLEntities - copy означает передачу права собственности, и ARC создает соответствующий код.
  • Добавьте в заголовок NS_RETURNS_RETAINED к определению метода следующим образом: - (NSString *)stringByEscapingXMLEntities NS_RETURNS_RETAINED.

РЕДАКТИРОВАТЬ: Как упоминалось в «iljawascoding»,@autoreleasepool не нуждается в реальной поддержке - за исключением оптимизации.


РЕДАКТИРОВАТЬ 2: И помните: ARC всегда делает правильные вещи ,Все, что вы пробовали (ваш комментарий), приводит к той же самой правильной программе - хотя и с отсутствием некоторой оптимизации, если результат был определен как __strong.

2 голосов
/ 25 января 2012

Код, который вы опубликовали, верен.У любого сбоя есть другая причина.

Поскольку result является сильной ссылкой за пределы области автоматического выпуска, ARC отвечает за поддержание его работоспособности при выходе из пула, и это так.Вам не нужно делать ничего особенного.

В частности, ARC генерирует код, эквивалентный следующему:

void *_arp = objc_autoreleasePoolPush();
temp1 = objc_retainAutoreleasedReturnValue([self stringByReplacingOccurrencesOfString:@"&" withString:@"&"]);
temp2 = objc_retainAutoreleasedReturnValue([temp1 stringByReplacingOccurrencesOfString:@"\"" withString:@"""]);
objc_release(temp1);
result = objc_retainAutoreleasedReturnValue([temp2 stringByReplacingOccurrencesOfString:@" " withString:@" "]);
objc_release(temp2);
// result is not released here
objc_autoreleasePoolPop(_arp);
return objc_autoreleaseReturnValue(result); // Result is returned autoreleased, or handed off to a  matching objc_retainAutoreleasedReturnValue() in the caller.

Обратите внимание, что временные переменные обрабатываются с помощью objc_retainAutoreleasedReturnValue / objc_releaseпар.Из-за оптимизации времени выполнения, реализованной objc_retainAutoreleasedReturnValue и objc_retainAutoreleasedReturnValue, это означает, что временные значения будут фактически освобождены немедленно, даже не помещаясь в пул автоматического выпуска , если -stringByReplacingOccurrencesOfString: построен с ARC.Я думаю, что большинство системных фреймворков еще нет.

2 голосов
/ 17 января 2012

Избавиться от авто-релиза в целом.Согласно Apple, ARC автоматически вставит необходимую версию после того, как ваш код будет создан с временными экземплярами, хранящимися в «результате».Здесь нет ничего полезного, если вы создадите свой собственный пул авто-релизов.

0 голосов
/ 17 января 2012

Почему бы не использовать [[NSString alloc] initWithString:result] до закрытия области действия @autoreleasepool? Но почему ARP на первом месте?

...