Когда ARC включена, то будет о быть введен в autorelease пул в этом коде фрагмент кода?
Ответ может быть, может быть, или нет. ARC не дает гарантии в любом случае. Здесь имя метода (obj
) не начинается с одного из специальных имен, которые указывают на сохраненный тип возврата (например, alloc
, retain
, new
, copy
, mutableCopy
), поэтому он возвращает не сохраненную ссылку. ARC specification section on "Unretained return values" говорит:
В худшем случае это может повлечь за собой autorelease, но абоненты должны не считать, что значение на самом деле в autorelease бассейне.
В старые времена, под MRC, вы должны были сделать autorelease
это в этом случае, прежде чем вернуться, потому что метод должен возвращать не-сохранить ссылку, но кто-то должен иметь сильную ссылку на объект иначе он будет освобожден. Поскольку объект был создан в вашем методе, никто не имеет ссылки на него, и этот метод должен избавиться от его сильной ссылки в конце своей области, поскольку он не может вернуть сохраненную ссылку, поэтому единственный способ - autorelease pool имеют сильную ссылку на возврат.
ARC должен оставаться совместимым с ABI с MRC (то есть вы должны иметь возможность заменить реализацию MRC с помощью ARC или наоборот, без изменения заголовков и вызывающих абонентов не нужно знать, была ли она скомпилирована с ARC или MRC работайте правильно). Поэтому в случае, когда ваш метод вызывается из кода MRC, следуя той же логике, что и в предыдущем абзаце, ваш метод должен быть autorelease
; просто нет другого способа сделать это.
Однако ARC представляет собой умную опциональную оптимизацию времени выполнения, которая может устранить autorelease
в некоторых случаях, когда вызывающий и вызываемый команды скомпилированы с помощью ARC, без вызова вызывающего абонента или вызывающего абонента, который должен знать о другой стороне. Это примерно так, как это работает: при возврате функции, где вы обычно бывали autorelease
, ARC вместо этого звонит objc_autoreleaseReturnValue()
. И в коде, который вызывает функцию и сохраняет возвращаемое значение, вместо этого он вызывает objc_retainAutoreleasedReturnValue()
. В objc_autoreleaseReturnValue()
он обращается к обратному адресу до кадра стека, чтобы узнать, будет ли возвращенное значение передано objc_retainAutoreleasedReturnValue()
. Если нет, то это будет autorelease
. Если это так, то он пропустит autorelease
, а также изменит адрес возврата, чтобы пропустить objc_retainAutoreleasedReturnValue
, таким образом удалив как autorelease
, так и retain
, что отменяет. В objc_retainAutoreleasedReturnValue()
, если он не пропущен, он будет только retain
. Это корректно работает для вызовов MRC-ARC, вызовов ARC-ARC и вызовов ARC-to-MRC и устраняет autorelease
для некоторых вызовов ARC-ARC.
Более того, в чем разница между этими двумя фрагментами кода?
Первый будет помещен в пул авторефератов, а второй - нет. (Кстати, __strong
по умолчанию, так что третья часть кода идентична первой.)
Но нет, по существу, нет веских причин использовать __autoreleasing
для локальной переменной вместо значения по умолчанию (который __strong
) ; __strong
проще и проще думать.
Обычно единственный раз, когда вы столкнетесь с __autoreleasing
в «указатель на» типы в параметрах - если функция объявляет, что оно принимает указатель на __autoreleasing
(например NSObject * __autoreleasing *
), это означает, что он будет писать в указываемом переменная по-другому, чем если она принимает указатель на __strong
(например, NSObject * __strong *
). Оба способа работают, но вызывающий и вызывающий должны согласовать, какой из них. Из-за вездесущего использования NSError * __autoreleasing *
в какао неквалифицированный по умолчанию указатель на __autoreleasing
(например, NSObject **
означает NSObject * __autoreleasing *
).
Ответ на первый вопрос: Да. Просто все равно. – dasdom