Какие детали «Objective-C Literals» упоминаются в примечаниях к выпуску Xcode 4.4?

188

Я просматривал заметки о выпуске для Xcode 4.4 и заметил это:

Компилятор LLVM 4.0

Xcode теперь включает в себя Apple LLVM Compiler версии 4.0, включая следующие новые функции языка
Objective-C : [...] - Литералы Objective-C: создают литералы для NSArray, NSDictionary и NSNumber, точно так же, как литералы для NSString

Я заинтригован об этой функции. Мне не совсем понятно, как литералы для NSStringработы и как их использовать NSArray, NSDictionaryи NSNumber.

Какие детали?

Педро Манчено
источник
Не ответ, но здесь есть некоторые предположения: reddit.com/r/programming/comments/pso6x/xcode_43_released/…
Arjan Tijms
3
"Разве этот материал не подлежит NDA?" А у тебя проблема?
Hejazzman
7
Нет, Apple явно заявила, что эти добавления не являются NDA в списке рассылки.
Griotspeak
2
У LLVM есть несколько документов на эту тему
Стивен Крамер,
3
Вот ссылка непосредственно на обсуждение Clang литералов Objective-C: clang.llvm.org/docs/ObjectiveCLiterals.html
ThomasW

Ответы:

393

Дословно скопировано с http://cocoaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and :

Литералы Objective C: теперь можно создавать литералы для NSArray, NSDictionary и NSNumber (точно так же, как можно создавать литералы для NSString)

NSArray Литералы

Ранее:

array = [NSArray arrayWithObjects:a, b, c, nil];

Сейчас:

array = @[ a, b, c ];

NSDictionary Литералы

Ранее:

dict = [NSDictionary dictionaryWithObjects:@[o1, o2, o3]
                                   forKeys:@[k1, k2, k3]];

Сейчас:

dict = @{ k1 : o1, k2 : o2, k3 : o3 };

NSNumber Литералы

Ранее:

NSNumber *number;
number = [NSNumber numberWithChar:'X'];
number = [NSNumber numberWithInt:12345];
number = [NSNumber numberWithUnsignedLong:12345ul];
number = [NSNumber numberWithLongLong:12345ll];
number = [NSNumber numberWithFloat:123.45f];
number = [NSNumber numberWithDouble:123.45];
number = [NSNumber numberWithBool:YES];

Сейчас:

NSNumber *number;
number = @'X';
number = @12345;
number = @12345ul;
number = @12345ll;
number = @123.45f;
number = @123.45;
number = @YES;

[Редактировать]

zxoq на http://news.ycombinator.com/item?id=3672744 добавил более интересные новые подписки. (Добавлено с литералами):

arr[1]      === [arr objectAtIndex:1]
dict[@"key"] === [dict objectForKey:@"key"]

[Редактировать 2]

Новые литералы ObjC обсуждались на нескольких сессиях WWDC 2012 . Я специально не удалил имена файлов и время каждого слайда, чтобы вы могли найти их сами, если захотите. По сути, это то же самое, что указано в этом посте, но есть также несколько новых вещей, которые я упомяну над изображениями.

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

Литералы и бокс

[NSNumber numberWithint:42]
[NSNumber numberWithDouble:10.8]
[NSNumber numberWithBool:YES]
[NSNumber numberWithint:6 + x * 2012]

Литералы и бокс

@42
@10.8
@YES
@(6 + x * 2012)

Подписка на коллекции

[NSArray arrayWithObjects: a, b, c, nil]
[array objectAtIndex:i]
[NSDictionary dictionaryWithObjectsAndKeys: v1, k1, v2, k2, nil];
[dictionary valueForKey:k]

Подписка на коллекции

@[a, b, c]
array[i]
@{k1:v1, k2:v2}
dictionary[k]

@ # числа, @ {} словари, @ "" строки, @ [] массивы, выражения @ ()


Эта часть новая. Выражение Литералы

Если у вас есть выражение ( M_PI / 16например), вы должны поместить его в круглые скобки.

Этот синтаксис работает для числовых выражений, логических выражений, поиска индекса в строке (C-), логических значений, констант enum и даже символьных строк!

Выражение Литералы

NSNumber *piOverSixteen = [NSNumber numberWithDouble: (M_PI / 16)];

NSNumber *hexDigit = [NSNumber numberWithChar:"0123456789ABCDEF"[i % 16]];

NSNumber *usesScreenFonts = [NSNumber numberWithBool:[NSLayoutManager usesScreenFonts]];

NSNumber *writingDirection = [NSNumber numberWithInt:NSWritingDirectionLeftToRight];

NSNumber *path = [NSString stringWithUTF8String: getenv("PATH")];

Выражение Литералы

NSNumber *piOverSixteen = @( M_PI / 16 );

NSNumber *hexDigit = @( "0123456789ABCDEF"[i % 16] );

NSNumber *usesScreenFonts = @( [NSLayoutManager usesScreenFonts] );

NSNumber *writingDirection = @( NSWritingDirectionLeftToRight );

NSNumber *path = @( getenv("PATH") );

Подробнее о символьных строках и о том, как / когда вы можете использовать этот буквальный синтаксис:

Выражения в штучной упаковке

NSString *path = [NSString stringWithUTF8String: getenv("PATH")];
for (NSString *dir in [path componentsSeparatedByString: @":"]) {
    // search for a file in dir...
}

Выражения в штучной упаковке

NSString *path = @( getenv("PATH") );
for (NSString *dir in [path componentsSeparatedByString: @":"]) {
    // search for a file in dir...
}

Как работают массивы литералов

Как работают массивы литералов

// when you write this:
array = @[a, b, c ];

// compiler generates:
id objects[] = { a, b, c };
NSUInteger count = sizeof(objects) / sizeof(id);
array = [NSArray arrayWithObjects:objects count:count];

Как работают словарные литералы

Как работают словарные литералы

// when you write this:
dict = @{k1 : o1, k2 : o2, k3 : o3 };

// compiler generates:
id objects[] = { o1, o2, o3 };
id keys[] = { k1, k2, k3 };
NSUInteger count = sizeof(objects) / sizeof(id);
dict = [NSDictionary dictionaryWithObjects:objects
                                   forKeys:keys
                                     count:count];

Подробнее о подписке на массив

Подписка на массив

@implementation SongList {
    NSMutableArray *_songs;
}

- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
    Song *oldSong = [_songs objectAtIndex:idx];
    [_songs replaceObjectAtindex:idx withObject:newSong];
    return oldSong;
}

Подписка на массив

@implementation SongList {
    NSMutableArray *_songs;
}

- (Song *)replaceSong:(Song *)newSong atindex:(NSUinteger)idx {
    Song *oldSong = _songs[idx];
    _songs[idx] = newSong;
    return oldSong;
}    

Подробнее о подписке на словарь

Подписка на словарь

@implementation Database {
    NSMutableDictionary *_storage;
}

- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
    id oldObject = [_storage objectForKey:key];
    [_storage setObject:object forKey:key];
    return oldObject;
}

Подписка на словарь

@implementation Database {
    NSMutableDictionary *_storage;
}

- (id)replaceObject:(id)newObject forKey:(id <NSCopying>)key {
    id oldObject = _storage[key];
    _storage[key] = newObject;
    return oldObject;
}

[Редактировать 3]

У Майка Эша есть отличная рецензия на эти новые литералы. Если вы хотите узнать больше об этом материале, не забудьте проверить это .


Поория Азими
источник
9
Я вижу, как это ускоряет мой код!
Педро Манчено
12
Есть ли способ получить xCode 4.3 для поддержки этих новых обозначений? Я хочу их - СЕЙЧАС ... но ТАК не "идет в гору" для них ...
Алекс Грей
20
У вас есть много текстового содержимого, встроенного в изображения, которые были бы более доступны поисковой системе, если бы они были опубликованы в виде простого текста.
Билл Ящерица
5
@BilltheLizard Я с уважением не согласен. Большая часть теста либо не-поиск вещь , как {и [, или общие слова , как array, idи @implementation. Соответствующие ключевые слова literal, objcа xcodeне конкретные упоминания [или @implementation. Вы не хотите, чтобы этот вопрос отображался для общих запросов ObjC в Google, он должен отображаться только тогда, когда кто-то запрашивает objc literal, что происходит в настоящее время (благодаря заголовку и тегам).
Пури Азими
4
Теперь это называется ответом StackOverflow. Хорошая работа поори.
Нитиш
15

Компилятор Objective-C обладает жестко запрограммированным знанием расположения в памяти экземпляров NSConstantStringкласса, или __CFConstantStringкласса. Проверьте RewriteObjCStringLiteralфункцию lib/Rewrite/RewriteModernObjC.cppв исходном коде Clang. Компилятор просто выдает данные, которые соответствуют расположению экземпляров NSConstantStringкласса.

Есть несколько возможностей для литерала NSArrayи NSDictionaryэкземпляров. Они могли бы сделать что-то вроде того, что они сделали для буквенных строк - жестко закодировать макет экземпляра (для специального подкласса) в компиляторе и выдать данные в этом макете. Или они могут иметь код, генерирующий компилятор, который просто создает экземпляр во время выполнения.

Роб Майофф
источник
2
Реализация литерального синтаксиса объекта для NSArrayи NSDictionaryсовсем не похожа на реализацию NSString. Компилятор просто генерирует вызов NSDictionaryили NSArrayво время выполнения. Именно поэтому глобальные переменные не могут быть инициализированы с использованием этого синтаксиса (в отличие от NSString). Это потребовало бы, чтобы результат был постоянной времени компиляции.
Buzzy
1

Из «Литералы Objective-C»

1) NSNumber, NSDictionaryи NSArrayлитералы доступны в Xcode 4.4 .

2) NSDictionaryи для NSArrayподписки требуется " Xcode 4.4 и OS X 10.8 или более поздняя версия SDK " или " Xcode 4.5 и iOS 6 или более поздняя версия SDK "

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

Andz
источник
в той же статье говорится «Развертывание обратно на iOS 4» в столбце «Развертывание iOS»
code007
1
Я случайно использовал массивы литералов в проекте, который я скомпилировал с Xcode 4.5. Он отлично работает на iPad под управлением iOS5. Он не компилируется на Xcode 4.2, как я узнал, что сделал это.
JScarry
Подписка может быть выполнена для работы с Xcode 4.4 и iOS5 SDK, с которым она поставляется, если вы добавите заголовок: github.com/tewha/iOS-Subscripting/blob/master/…
Стивен Фишер