Objective-C in, out, inout, byref, byval,.. и так далее. Кто они такие?

Я обнаружил что-то незнакомое при чтении руководства Objective-C для @encoding.

Table 6-2  Objective-C method encodings
Code Meaning
r    const
n    in
N    inout
o    out
O    bycopy
R    byref
V    oneway

Единственное, что я знаю, это oneway. Что другие?

Ответ 1

Это аннотации параметров метода и возвращаемых значений, которые использовались Distributed Objects. Я говорю, потому что, по-видимому, они больше не подписывают их в документации на Яблоки. Раньше был раздел "Удаленные сообщения" в документе "Язык программирования Objective-C", на который по-прежнему ссылается документ "Распространенные объекты".

  • in: аргумент является только входным аргументом и не будет упоминаться позже
  • out: аргумент - это только выходной аргумент, используемый для возврата значения по ссылке
  • inout: - аргумент ввода и вывода
  • const: аргумент (указатель) постоянный
  • bycopy: вместо прокси / NSDistantObject, передать или вернуть копию объекта
  • byref: использовать прокси-объект (по умолчанию)

Ответ 2

Помимо распределенных объектов, одна из этих аннотаций, по-видимому, используется ARC. Я наткнулся на следующее описание cla переход к выходному параметру путем обратной записи:

Если параметр не является параметром метода Objective-C, помеченным out, тогда читается *p, а результат записывается во временную примитивную семантику.

Это связано с такими методами, как - (BOOL)executeWithError:(out NSError **)error.

Игнорируя ключевое слово out, ARC имеет корректное поведение обработки объекта-ссылки, проходящего как __autoreleasing, поэтому ARC обрабатывает параметр error как имеющий тип NSError * __autoreleasing *. Если вы используете переменную, отличную от другой, ARC добавит временную передачу переменной autoreleasing в функцию (для согласованности):

Исходный код

NSError *error;
[obj executeWithError:&error];

Pseudotransformed code

NSError * __strong error;
NSError * __autoreleasing temp;
temp = error;
[obj executeWithError:&temp];
error = temp;

С приведенным выше кодом строка temp = error не понадобилась бы, если бы мы как-то знали, что temp никогда не будет считаться. Здесь вступает в действие аннотация out. В цитированном описании, если out отсутствует, компилятор должен добавить строку temp = error, но если он содержит out, он может исключить строку и сделать код немного меньше/быстрее. С out преобразованный код становится:

NSError * __strong error;
NSError * __autoreleasing temp;
[obj executeWithError:&temp];
error = temp;

Конечно, если вы беспокоитесь о двоичном размере и скорости, вы должны просто закодировать следующее:

NSError * __autoreleasing error;
[obj executeWithError:&error];

Вполне возможно, что эти аннотации используются в других местах во всем компиляторе и во время выполнения и могут использоваться в будущем в других местах. Лично мне нравится использовать out как подсказку для других разработчиков, что я не буду читать значение.

Ответ 3

Если кто-нибудь наткнулся на этот пост и имеет ту же путаницу, что и я, аргумент "in" также может быть ключевым словом, которое представляет собой быстрое перечисление. Подробнее см. здесь.