Почему NSArray arrayWithObjects требует завершающегося ноля?

  • UTF-8 переменный 1 - 4 байты.

  • UTF-16 переменный 2 или 4 байты.

  • UTF-32 фиксируется 4 байты.

16
задан pjb3 21 August 2009 в 00:31
поделиться

4 ответа

Все это связано с вызовом ABI языка C.

Рассмотрим следующие методы:

- (id)initWithFormat:(NSString *)format, ...;
+ (id)arrayWithObjects:(id)firstObj, ...;
+ (id)dictionaryWithObjectsAndKeys:(id)firstObject, ...;

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

Теперь рассмотрим три метода. Все три имеют совершенно разные требования к тому, что может присутствовать в списке переменных аргументов. Массив должен быть набором объектов, за которым следует ноль. Для словаря требуется набор пар объектов, за которыми следует ноль. Наконец, строковый метод требует набора аргументов, которые соответствуют типам в строке формата.

Все эти варианты поведения напрямую привязаны к вызываемому методу, и, если автор API решил пойти на "

18
ответ дан 30 November 2019 в 21:29
поделиться

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

Я предполагаю, что у вас есть массив, который может содержать ноль?

3
ответ дан 30 November 2019 в 21:29
поделиться

@bbum дает некоторые важные технические детали. Вот несколько мыслей о практических «почему они не исправят это?»

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

Одна вещь, которая должна стать ясной из обсуждения @ bbum: NSArray не является языковой функцией Objective-C. C-массивы - это функция языка, но NSArrays - это просто еще один объект, ничем не отличающийся от объектов, которые вы пишете.

t положить в массив nil (это потребовало бы огромных изменений). Компилятор теперь предупреждает вас, если вы забыли nil, поэтому разработчики не на что жалуются. Компромисс состоит в том, чтобы сохранить язык намного (намного!) Проще, чем его аналог, получить преимущества десятилетий оптимизации компилятора C и гарантированную совместимость с кодом C.

Одна вещь, которая должна стать ясной из обсуждения @ bbum: NSArray не является языковой функцией Objective-C. C-массивы - это функция языка, но NSArrays - это просто еще один объект, ничем не отличающийся от объектов, которые вы пишете.

t положить в массив nil (это потребовало бы огромных изменений). Компилятор теперь предупреждает вас, если вы забыли nil, поэтому разработчики не на что жалуются. Компромисс заключается в том, чтобы сохранить язык намного (намного!) Проще, чем его аналог, получить преимущества десятилетий оптимизации компилятора C и гарантированную совместимость с кодом C.

Одна вещь, которая должна стать ясной из обсуждения @ bbum: NSArray не является языковой функцией Objective-C. C-массивы - это функция языка, но NSArrays - это просто еще один объект, ничем не отличающийся от объектов, которые вы пишете.

получение преимуществ десятилетий оптимизации компилятора C и гарантированной совместимости с кодом C.

Одна вещь, которая должна стать ясной из обсуждения @ bbum: NSArray не является языковой особенностью Objective-C. C-массивы - это функция языка, но NSArrays - это просто еще один объект, ничем не отличающийся от объектов, которые вы пишете.

получение преимуществ десятилетий оптимизации компилятора C и гарантированной совместимости с кодом C.

Одна вещь, которая должна стать ясной из обсуждения @ bbum: NSArray не является языковой особенностью Objective-C. C-массивы - это функция языка, но NSArrays - это просто еще один объект, ничем не отличающийся от объектов, которые вы пишете.

2
ответ дан 30 November 2019 в 21:29
поделиться

Существуют различные обходные пути, но мой текущий фаворит больше подходит для приложений, чем для выпущенных фреймворков. Примите NSArray в своем методе вместо "...", а затем заполните его приведенным ниже удобным макросом, который помещен в файл префикса или заголовок утилиты.

#define $array(objs...) [NSArray arrayWithObjects: objs, nil]

Это позволит использовать несколько хорошо помеченных аргументов переменной длины, и вы избавитесь от архаичной схемы использования первый аргумент, а затем va_list и его собратья в пользу цикла for-in или многих других доступных инструментов сбора.

[self findMatchingSetAndAlert:@"title" ties:$array(tie1, tie2, tie3) shirts:$array(shirt1, shirt2, shirt3, shirt4)];

Если кто-то знает, как реализовать список без разделителей, например stringWithFormat, сообщите нам об этом! Он использует атрибуты и макросы или что-то, разработанное специально для форматирования, но это как-то реализовано.

2
ответ дан 30 November 2019 в 21:29
поделиться
Другие вопросы по тегам:

Похожие вопросы: