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

Есть ли буквальный синтаксис словаря или массива в Objective-C?

Всегда можно было создавать NSArrays (и NSDictionaries/NSNumber) с вызовами метода vararg, например:

[NSArray arrayWithObjects: @"a", @"b", @"c", nil];

Могут ли они быть созданы с помощью линейных литералов в новом улучшении для LLVM и Clang?

4b9b3361

Ответ 1

С это изменение в кодовую базу LLVM, Apple добавила новый синтаксис для литералов в будущих версиях компилятора Clang.

Раньше массивы создавались с использованием массива на основе C и преобразовывались на лету в объекты Objective-C, такие как:

NSArray* array = [NSArray arrayWithObjects: @"One", @"Two", @"Three", nil];

Обратите внимание, что поскольку это элемент varargs, вы должны были предоставить конец "nil" в конце списка. Однако теперь есть более простой способ:

NSArray* array = @[ @"One", @"Two", @"Three" ];

Обратите внимание на то, что перед @необходимо указать ведущее @, чтобы различать его и обычный массив C (или отправить сообщение). Обратите также внимание на то, что конечное "ноль" больше не требуется.

Аналогичное изменение было сделано для линейных словарных литералов, похожих на структуры JSON:

NSDictionary* dict = @{
    @"Key1": @"Value1",
    @"Key2": @"Value2",
};

Наконец, добавлен новый литерал для NSInteger (и т.д.):

NSNumber* value = @3.141;

Обратите внимание, что хотя это работает для с плавающей запятой (@3.141F) и double (@3.141), это не работает для long double, поскольку они не поддерживаются для упаковки компилятором. Таким образом, @3.141D будет ошибкой времени компиляции.

Из-за того, как определены константы, @INT_MAX является допустимым допустимым значением, но @INT_MIN не является, поскольку последнее определяется с помощью выражения времени компиляции, а не самого литерала.

Существуют также расширения для булевых типов:

NSNumber* yes = @YES;         // [NSNumber numberWithBool:YES]
NSNumber* no = @NO;           // [NSNumber numberWithBool:NO]
NSNumber* trueBool = @true;   // [NSNumber numberWithBool:(BOOL)true]
NSNumber* falseBool = @false; // [NSNumber numberWithBool:(BOOL)false]

Это изменение также ввело литералы __objc_yes и __objc_no, чтобы поддерживать разбор типов только по буквальному значению. Их использование охраняется с помощью #if __has_feature(objc_bool) в препроцессоре, но разработчики должны продолжать использовать YES и NO в коде.

Наконец, как массивы, так и словари теперь можно индексировать с помощью скобок массива, используя как выражения lvalue, так и rvalue:

NSMutableArray* stuff = ...
id first = stuff[0];
stuff[0] = anotherObject;

NSMutableDictionary* moreStuff = ...
id conference = moreStuff[@"NSConf"]
moreStuff[@"SponsoredBy"] = @"NSConfDuck"

Подписчик стиля массива (с использованием NSUInteger) отображается на objectAtIndexedSubscript: и соответствующий setObject:atIndexedSubscript:, в то время как доступ к словарю осуществляется с помощью objectForKeyedSubscript: и setObject:forKeyedSubscript:

Полный синтаксис для литералов можно увидеть на веб-сайте Clang/LLVM

Обратите внимание, что, поскольку этот ответ был изначально написан, Clang добавил поддержку нелитеральных выражений Objective-C, называемых "Boxed expressions"

Это означает, что можно использовать @(3+4) как эквивалент @7 и @("Hello World") как @"Hello World". Обратите внимание, что выражение C, которое оценивается как null, приведет к исключению, а аргументы, такие как @(null), рассматриваются как ошибка времени компиляции.

Также можно использовать "Boxed enums" для типов с известным типом, поэтому

enum {   Север,   Юг,   Восток,   Запад, };

может быть помещен в коробчатый тип перечисления с @(North), который будет иметь значение 0.

Вставные выражения будут доступны в clang 3.2 и далее. Он может быть протестирован для использования теста препроцессора __has_feature(objc_boxed_expressions).