Como faço para converter um NSString em um std :: string?

Respostas:

134
NSString *foo = @"Foo";
std::string bar = std::string([foo UTF8String]);

Edit: Depois de alguns anos, deixe-me expandir esta resposta. Como corretamente apontado, você provavelmente desejará usar cStringUsingEncoding:comNSASCIIStringEncoding se for acabar usando std::string. Você pode usar UTF-8 com normal std::strings, mas lembre-se de que eles operam em bytes e não em caracteres ou mesmo grafemas. Para um bom "começo", verifique esta pergunta e sua resposta .

Observe também que, se você tem uma string que não pode ser representada como ASCII, mas ainda quer em um std::stringe não quer caracteres não ASCII lá, você pode usar dataUsingEncoding:allowLossyConversion:para obter uma NSDatarepresentação da string com ASCII codificado com perdas conteúdo e, em seguida, jogue-o em seustd::string

JustSid
fonte
13
Cuidado com a codificação. Embora UTF-8 seja geralmente uma boa escolha, se a API com a qual você está trabalhando espera, digamos, ASCII puro ou a página de código do sistema, você terá que usar em seu -cStringUsingEncoding:lugar. :)
Jonathan Grynspan
13
Este é um vazamento de memória se você não excluí-lo, o ponteiro retornado não é um objeto contado de referência Objective-C. Em geral, você deve evitar usar o operador new para std :: string.
SiimKallas
Esta não deve ser a resposta aceita e definitivamente não é a primeira coisa a se considerar ao fazer essa conversão.
JBL
@JBL Depois de apenas 4 anos e algumas semanas, comecei a expandir minha resposta. Espero que seja mais aceitável agora.
JustSid
@JustSid Eu deveria ter explicado minha opinião, mas a outra questão é o uso de um ponteiro por padrão. Aliás, um colega de trabalho com formação ObjC, sem nenhum conhecimento de C ++, usou que, sem deletar, acabou em um vazamento de memória. E mais geralmente; selvagens newsão desaprovados e um std::shared_ptrou std::unique_ptrdeve ser preferido.
JBL
50

Como Ynau sugeriu no comentário, em um caso geral, seria melhor manter tudo na pilha em vez de no heap (usando newcria a string no heap), portanto (assumindo a codificação UTF8):

NSString *foo = @"Foo";
std::string bar([foo UTF8String]);
Marco83
fonte
8

Conforme observado em philjordan.eu , também pode ser que o NSString esteja nil. Nesse caso, o elenco deve ser feito assim:

// NOTA: se foo for nulo, isso produzirá uma string C ++ vazia

// em vez de remover a referência do ponteiro NULL de UTF8String.

Isso levaria você a essa conversão:

NSString *foo = @"Foo";
std::string bar = std::string([foo UTF8String], [foo lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
Bruno Bieri
fonte
1
Isso é extremamente útil. Preocupar-se em ver que quase todo mundo está negligenciando isso. Vocês vão bater no NIL.
P i