Como converter std :: string em NSString?

97

Olá, estou tentando converter um padrão std::stringem um, NSStringmas não estou tendo muita sorte.

Posso converter com sucesso de um NSStringpara um std::stringcom o seguinte código

NSString *realm = @"Hollywood";
std::string REALM = [realm cStringUsingEncoding:[NSString defaultCStringEncoding]];

No entanto, recebo um erro de tempo de compilação quando tento o seguinte

NSString *errorMessage = [NSString stringWithCString:REALM encoding:[NSString defaultCStringEncoding]];

O erro que recebo é

Cannot convert 'std::string' to 'const char*' in argument passing

Estou faltando alguma coisa aqui?

Desde já, obrigado.

Anthony McCormick
fonte
4
Deve ser um erro de digitação, mas está faltando '@' para literal de string em 'NSString * realm = "Hollywood";' linha.
Vladimir

Respostas:

111

Obtenha a string C de std :: string para conversão:

NSString *errorMessage = [NSString stringWithCString:REALM.c_str() 
                                   encoding:[NSString defaultCStringEncoding]];
Vladimir
fonte
Esta não parece ser uma boa resposta, como diz a documentação: / * Codificação dependente do usuário cujo valor é derivado do idioma padrão do usuário e potencialmente outros fatores. O uso dessa codificação pode às vezes ser necessário ao interpretar documentos do usuário com codificações desconhecidas, na ausência de outras dicas. Essa codificação deve ser usada raramente, se alguma. Observe que alguns valores potenciais aqui podem resultar em conversões de codificação inesperadas de conteúdo NSString bastante simples - por exemplo, caracteres de pontuação com codificação bidirecional. * /
cyrilchampier
30
[NSString stringWithUTF8String: mystring.c_str ()] parece mais apropriado, uma vez que std :: string vem mais provavelmente de seu próprio código, que provavelmente está em UTF8.
cyrilchampier
Vocês sabem por que aqui ( developer.apple.com/documentation/foundation/nsstring/… ) diz “O objeto retornado pode ser diferente do receptor original”? O que isso significa e como saberemos se é diferente?
Julian00,
@cyrilchapier e se nosso arquivo .mm disser “nenhuma codificação específica especificada”?
is Julian00
53

Em primeiro lugar, você tem que usar Objective-C ++ para que isso funcione no mínimo; maneira mais fácil de garantir que é renomear todos os seus*.m arquivos para*.mm

De longe, a maneira manual mais utilizável (não obsoleta) de std::stringinserir um C ++ em um NSStringé com:

std::string param; // <-- input
NSString* result = [NSString stringWithUTF8String:param.c_str()];
NSString* alternative = [[NSString alloc] initWithUTF8String:param.c_str()];

Isso funcionará na maioria dos casos - e se você não estiver fazendo uma detecção e conversão de codificação específica, o UTF-8 vai lhe dar um bom resultado por ter caracteres não latinos 'apenas funcionam'.

Se você estiver fazendo um aplicativo maior ou não for o único trabalhando nele, provavelmente desejará algo mais fácil de aplicar.

Adaptado dos arquivos da lista de discussão cocoa-dev

@interface NSString (cppstring_additions)
+(NSString*) stringWithwstring:(const std::wstring&)string;
+(NSString*) stringWithstring:(const std::string&)string;
-(std::wstring) getwstring;
-(std::string) getstring;
@end

@implementation NSString (cppstring_additions)

#if TARGET_RT_BIG_ENDIAN
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32BE);
#else
const NSStringEncoding kEncoding_wchar_t = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingUTF32LE);
#endif

+(NSString*) stringWithwstring:(const std::wstring&)ws
{
    char* data = (char*)ws.data();
    unsigned size = ws.size() * sizeof(wchar_t);

    NSString* result = [[NSString alloc] initWithBytes:data length:size encoding:kEncoding_wchar_t];
    return result;
}
+(NSString*) stringWithstring:(const std::string&)s
{
    NSString* result = [[NSString alloc] initWithUTF8String:s.c_str()];
    return result;
}

-(std::wstring) getwstring
{
    NSData* asData = [self dataUsingEncoding:kEncoding_wchar_t];
    return std::wstring((wchar_t*)[asData bytes], [asData length] / sizeof(wchar_t));
}
-(std::string) getstring
{
    return [self UTF8String];
}

@end

Com isso instalado (e apropriadamente #imported) agora você pode:

NSString* result = [NSString stringWithstring:param];
string convertedBack = [result getstring];

E o mesmo para std::wstring, o que é mais do que útil.

rvalue
fonte
1
Isso é incrível e eu usei em alguns projetos de iphone. Uma coisa que notei foi que se eu estivesse executando o framework de teste de unidade da Apple e estivesse testando uma biblioteca que utiliza esses métodos, eu tinha que incluir o arquivo contendo os métodos de conversão de string como um dos "Compile Sources" nas "Build Phases" para o teste de unidade. Esquisito.
David
1
Sim, o teste de unidade é essencialmente seu próprio programa e precisa ter acesso ao mesmo código. Além disso, parabéns por realmente escrever testes ;-)
rvalue
1
Vocês sabem por que aqui ( developer.apple.com/documentation/foundation/nsstring/… ) diz “O objeto retornado pode ser diferente do receptor original”? O que isso significa e como saberemos se é diferente?
Julian00,
1
@izzyMachado esse tipo de linguagem nos documentos normalmente significa que eles se reservam o "direito", de acordo com o contrato de interface, de analisar, higienizar ou canonizar a string de entrada. ou seja, pode não ser de ida e volta e ainda assim comparar, ==mas sim ser a representação "mais próxima" ou "melhor" que eles podem fazer. O receptor, neste caso, é a NSStringimplementação da classe e o valor retornado não é um objeto Objective-C, então eles também podem estar cobrindo isso com alguma linguagem padrão.
rvalue
Você sabe por que isso ainda funciona quando usamos initWithUTF8String e a string inclui caracteres não utf8, como ele ainda é capaz de usar a string (se for Mint UTF-8) e imprimi-la assim que se tornar um NSString?
Julian00,
21
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];
John Bowers
fonte
isso torna o NSString UTF8? ou que codificação seria o NSString?
Julian00
14

A Apple agora tem uma nova maneira pela qual desejam que você faça essa conversão. No XCode7, usei a opção Edit> Convert> To Modern Objective C Syntax ... para descobrir isso. Ele usa um símbolo @ abreviado.

std::string sCPPString = "Hello World!";
NSString *sAppleString = @(sCPPString.c_str());
Volomike
fonte
3

Eu também descobri que:

NSString *nsString = [NSString stringWithFormat:@"%s",standardString];

Trabalha como um campeão.

BadPirate
fonte
3
Isso é muito inseguro e não é garantido que funcione. standardString se um std :: string, é um objeto C ++. Objetos C ++ não são seguros para passar para funções variadic (templates variadic resolvem este problema em C ++ 11). Se funcionar, é um acaso e quase todos os compiladores irão no mínimo alertá-lo contra fazer isso (se não for um erro para começar).
Vitali,
3

Aqui está o snippet de código / exemplo:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
Deepak Kumar
fonte