Quais são os detalhes de "Literais Objective-C" mencionados nas notas de versão do Xcode 4.4?

188

Eu estava examinando as notas de versão do Xcode 4.4 e percebi o seguinte:

Compilador LLVM 4.0

O Xcode agora inclui o Apple LLVM Compiler versão 4.0, incluindo os seguintes recursos da linguagem newObjective-C: [...]
- literais de Objective-C: criam literais para NSArray, NSDictionary e NSNumber, exatamente como os literais para NSString.

Estou intrigado com esse recurso. Não é totalmente claro para mim o quão literais para NSStringo trabalho e como se poderia usá-los em NSArray, NSDictionarye NSNumber.

Quais são os detalhes?

Pedro Mancheno
fonte
Não é uma resposta, mas há alguma especulação aqui: reddit.com/r/programming/comments/pso6x/xcode_43_released/...
Arjan Tijms
3
"Este material não está sujeito a um NDA?" E o seu problema é?
21412 Hejazzman
7
Não, a Apple disse explicitamente que essas adições não são NDA na lista de distribuição.
griotspeak
2
LLVM tem alguns documentos sobre este assunto: clang.llvm.org/docs/LanguageExtensions.html#objc_lambdas
Steven Kramer
3
Aqui está um link diretamente para a discussão Clang de literais Objective-C: clang.llvm.org/docs/ObjectiveCLiterals.html
Thomasw

Respostas:

393

Copiado literalmente de http://cocoaheads.tumblr.com/post/17757846453/objective-c-literals-for-nsdictionary-nsarray-and :

Literais Objective-C: agora é possível criar literais para NSArray, NSDictionary e NSNumber (assim como se pode criar literais para NSString)

NSArray Literals

Anteriormente:

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

Agora:

array = @[ a, b, c ];

Literais do NSDictionary

Anteriormente:

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

Agora:

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

Literais NSNumber

Anteriormente:

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];

Agora:

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

[Editar]

O zxoq em http://news.ycombinator.com/item?id=3672744 adicionou uma nova inscrição mais interessante. (Adicionado com literais):

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

[Editar 2]

Os novos literais da ObjC foram discutidos em várias sessões da WWDC 2012 . Intencionalmente, não removi os nomes dos arquivos e a hora de cada slide, para que você possa encontrá-los por conta própria, se quiser. Eles são essencialmente a mesma coisa que afirmamos neste post, mas também há algumas coisas novas que mencionarei acima das imagens.

Observe que as imagens são todas grandes. Basta arrastá-los para outra guia para visualizá-los no tamanho original

Literais e Boxe

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

Literais e Boxe

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

Subscrição de Coleção

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

Subscrição de Coleção

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

@ # números, @ {} dicionários, @ "" strings, @ [] matrizes, @ () expressões


Esta parte é nova. Literais de Expressão

Quando você tem uma expressão ( M_PI / 16por exemplo), deve colocá-la entre parênteses.

Essa sintaxe funciona para expressões numéricas, booleanos, localizando um índice em uma string (C-), valores booleanos, constantes enum e até strings de caracteres!

Literais de Expressão

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")];

Literais de Expressão

NSNumber *piOverSixteen = @( M_PI / 16 );

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

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

NSNumber *writingDirection = @( NSWritingDirectionLeftToRight );

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

Mais sobre cadeias de caracteres e como / quando você pode usar esta sintaxe literal:

Expressões de string em caixa

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

Expressões de string em caixa

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

Como literais de matriz funcionam

Como literais de matriz funcionam

// 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];

Como os literais do dicionário funcionam

Como os literais do dicionário funcionam

// 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];

Mais sobre assinatura de array

Subscrição de Matrizes

@implementation SongList {
    NSMutableArray *_songs;
}

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

Subscrição de Matrizes

@implementation SongList {
    NSMutableArray *_songs;
}

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

Mais sobre subscrição de dicionário

Subscrição de Dicionário

@implementation Database {
    NSMutableDictionary *_storage;
}

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

Subscrição de Dicionário

@implementation Database {
    NSMutableDictionary *_storage;
}

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

[Editar 3]

Mike Ash tem um ótimo artigo sobre esses novos literais. Se você quiser saber mais sobre esse material, verifique .


Pooria Azimi
fonte
9
Eu posso ver isso acelerando minha codificação!
Pedro Mancheno
12
Existe alguma maneira de obter o xCode 4.3 para suportar essas novas notações? Eu quero que eles - EMPRESA ... mas estou SO não "subir a montanha" para eles ...
Alex Gray
20
Você tem muito conteúdo textual incorporado nas imagens aqui que seriam mais acessíveis por um mecanismo de pesquisa se ele fosse publicado como texto sem formatação.
Bill the Lizard
5
@ BilltheLizard Eu discordo respeitosamente. A maior parte do teste é o UN-pesquisável coisas como {e [, ou são palavras genéricas como array, ide @implementation. As palavras-chave relevantes são literal, objce xcodenão as menções específicas de [ou @implementation. Você não deseja que essa pergunta apareça para consultas gerais sobre ObjC no Google, ela deve ser exibida apenas quando alguém fizer uma consulta objc literal, o que acontece no momento (graças ao título e às tags).
Pooria Azimi
4
Agora isso é chamado de resposta StackOverflow. Bom trabalho, Pooria.
Nitish
15

O compilador Objective-C codificou o conhecimento do layout de memória das instâncias da NSConstantStringclasse, também conhecida como __CFConstantStringclasse. Confira a RewriteObjCStringLiteralfunção no lib/Rewrite/RewriteModernObjC.cppcódigo-fonte do clang. O compilador simplesmente emite dados que correspondem ao layout das instâncias doNSConstantString classe.

Existem algumas possibilidades para literais NSArraye NSDictionaryinstâncias. Eles poderiam fazer algo parecido com o que fizeram para seqüências de caracteres literais - codificar o layout da instância (para uma subclasse especial) no compilador e emitir dados nesse layout. Ou eles podem fazer o compilador emitir um código que simplesmente cria uma instância em tempo de execução.

Rob Mayoff
fonte
2
A implementação da sintaxe literal do objeto para NSArraye NSDictionaryé bem diferente da de NSString. O compilador simplesmente gera uma chamada para NSDictionaryou NSArrayem tempo de execução. É também por isso que variáveis ​​globais não podem ser inicializadas usando esta sintaxe (diferente NSString). Isso exigiria que o resultado fosse uma constante de tempo de compilação.
Buzzy
1

Dos literais de Objective-C

1) NSNumber, NSDictionarye NSArrayliterais estão disponíveis em Xcode 4,4 .

2) NSDictionarye a NSArrayassinatura precisa do " Xcode 4.4 e OS X 10.8 ou posterior SDK " ou " Xcode 4.5 e iOS 6 ou posterior SDK "

Parece-me que a assinatura precisa de suporte de tempo de execução e, portanto, não funcionará antes do iOS6 .

Andz
fonte
no mesmo artigo, ele diz "Implanta de volta no iOS 4" na coluna 'Implantação do iOS'
code007
1
Eu acidentalmente usei literais de matriz em um projeto que compilei com o Xcode 4.5. Ele roda bem em um iPad com iOS5. Ele não é compilado no Xcode 4.2, e foi assim que descobri que o fiz.
JScarry
Subscripting pode ser feito para trabalhar com o Xcode 4.4 eo SDK iOS5 ele vem com se você adicionar um cabeçalho: github.com/tewha/iOS-Subscripting/blob/master/...
Steven Fisher