Подтвердить что ты не робот

NSError и __autoreleasing

Может ли кто-нибудь объяснить мне цель иметь __autoreleasing в следующем примерном блоке кода?

- (void)execute:(NSError * __autoreleasing *)error {
    // do stuff, possibly assigning error if something went wrong
}

Я удалил __autoreleasing, и все, кажется, компилируется/работает нормально. Я начал использовать obj-c пост ARC, поэтому я никогда не узнавал/не понимал все эти двойные подчеркивания thingamajigs. Я прочитал Руководство по переходу ARC, но я не совсем понимаю их пример NSError.

4b9b3361

Ответ 1

Рассмотрим, как ARC работает с переменными - каждая ссылочная переменная имеет режим (неявный или явный): сильный, слабый и т.д. Этот режим позволяет ARC знать, как обрабатывать чтения и записи этой переменной; например для сильного чтения переменных не требуется никаких дополнительных действий, в то время как запись требует освобождения существующей ссылки в переменной до ее замены новым. ARC должен знать режим любой переменной, чтобы функционировать.

Теперь рассмотрим переменные, которые сами передаются по ссылке, например. для вашего execute у вас будет вызов по строкам:

NSError *myError = nil;
...
[someObject execute:&myError]; // pass the variable itself by reference, not the variables value

а тело execute будет содержать назначение по строкам:

- (void)execute:(NSError * __autoreleasing *)error
{
   ...
   if (error != NULL)
      *error = [NSError ...]; // assign indirectly via the reference to a variable
   ...
}

Теперь для этого косвенного назначения ARC должен знать режим ссылочной переменной, чтобы он знал, как читать и писать. Это то, что __autoreleasing находится в объявлении, он сообщает ARC, что ему была передана ссылка на переменную, режим которой автореализуется, и это говорит ARC, как читать и записывать содержимое переменной. Удалите __autoreleasing, и предполагается, что будет использоваться режим по умолчанию, и в этом случае я бы предположил, что явное, безусловно, хорошо.

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

Вы могли заметить, что в приведенном выше примере переменная myError имеет режим сильной (неявно) и все же передается по ссылке как автореализацию - компилятор обрабатывает это автоматически, вводя временную переменную автореализации, копируя, не сохраняя текущую ссылку в myError в него и передать временную ссылку в качестве аргумента execute:. После возврата вызова компилятор выполняет обычное присвоение от временного до myError, что приводит к освобождению любой старой ссылки, а возвращаемый сохраняется.

Подробнее см. Переход на Apple в примечания к выпуску ARC

Наблюдение за комментариями

Q: Непосредственно установлен __autoreleasing?

A: Хорошо Документ Apple не является конкретным, но документация Clang говорит, что он подразумевается для косвенных параметры. Как и выше, я рекомендую быть явным, ясность - это хорошая вещь.

Q: Имеет ли место размещение?

A: Да, и нет... Это декларация C, информация о опросх ( "Что объявляет следующее..." ). Квалификатор должен быть между двумя звездочками, поскольку он является указателем на указатель автореализации (переменной типа) для объекта, но Apple заявляет, что компилятор "прощает", не будучи конкретным из того, что он прощает. Играйте в безопасное место, положите его в нужное место.

В: Если вы не тестируете error как NULL перед выполнением косвенного назначения?

A: Конечно, вы должны, где-то, прежде чем сделать косвенное отношение. Показанный код - это всего лишь контур, и такая деталь была устранена и покрыта ... s. Однако, как это было несколько раз в течение нескольких лет, возможно, я слишком сильно отклонился, добавлен подходящий if.