Come convertire std :: string in NSString?


97

Salve, sto cercando di convertire uno standard std::stringin uno NSStringma non ho molta fortuna.

Posso convertire con successo da an NSStringa a std::stringcon il seguente codice

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

Tuttavia ricevo un errore in fase di compilazione quando provo quanto segue

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

L'errore che ottengo è

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

Mi manca qualcosa qui?

Grazie in anticipo.


4
Deve essere un errore di battitura, ma manca "@" per la stringa letterale in "NSString * realm =" Hollywood ";" linea.
Vladimir

Risposte:


111

Ottieni c-string da std :: string per la conversione:

NSString *errorMessage = [NSString stringWithCString:REALM.c_str() 
                                   encoding:[NSString defaultCStringEncoding]];

Questa non sembra essere una buona risposta, come dice la documentazione: / * Codifica dipendente dall'utente il cui valore è derivato dalla lingua predefinita dell'utente e potenzialmente da altri fattori. L'uso di questa codifica a volte potrebbe essere necessario quando si interpretano documenti utente con codifiche sconosciute, in assenza di altri suggerimenti. Questa codifica dovrebbe essere usata raramente, se non del tutto. Si noti che alcuni valori potenziali qui potrebbero causare conversioni di codifica inaspettate di contenuto NSString anche abbastanza semplice, ad esempio caratteri di punteggiatura con una codifica bidirezionale. * /
cyrilchampier

30
[NSString stringWithUTF8String: mystring.c_str ()] sembra più appropriato, poiché std :: string è più probabile che provenga dal tuo codice, che è probabilmente in UTF8.
cyrilchampier

Ragazzi, sapete perché qui ( developer.apple.com/documentation/foundation/nsstring/… ) c'è scritto "L'oggetto restituito potrebbe essere diverso dal destinatario originale"? Cosa significa e come potremmo sapere se è diverso?
Julian00

@cyrilchapier e se il nostro file .mm dicesse "nessuna codifica specifica specificata"?
Julian00

53

In primo luogo, devi usare Objective-C ++ perché funzioni al minimo; il modo più semplice per assicurarti di rinominare tutti i tuoi *.mfile in*.mm

Di gran lunga il modo manuale più utilizzabile (non deprecato) per ottenere un C ++ std::stringin un NSStringè con:

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

Questo funzionerà nella maggior parte dei casi - e se non stai effettuando il rilevamento e la conversione di codifiche specifiche, UTF-8 ti darà un buon risultato per avere caratteri non latini "semplicemente funzionanti".

Tuttavia, se stai creando un'app più grande o non sei l'unico a lavorarci, probabilmente vorrai qualcosa di più facile da applicare.

Adattato dagli archivi della mailing list di 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

Con quello sul posto (e adeguatamente #imported) ora puoi:

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

E lo stesso per std::wstring, che è più che utile.


1
Questo è fantastico e l'ho usato in un paio di progetti per iPhone. Una cosa che ho notato è che se stavo eseguendo il framework di unit test di Apple e stavo testando una libreria che utilizza questi metodi, dovevo includere il file contenente i metodi di conversione delle stringhe come una delle "Sorgenti di compilazione" nelle "Fasi di compilazione" per lo unit test. Strano.
David

1
Sì, lo unit test è essenzialmente un piccolo programma e deve avere accesso allo stesso codice. Inoltre, complimenti per aver scritto i test ;-)
rvalue

1
Ragazzi, sapete perché qui ( developer.apple.com/documentation/foundation/nsstring/… ) c'è scritto "L'oggetto restituito potrebbe essere diverso dal destinatario originale"? Cosa significa e come potremmo sapere se è diverso?
Julian00

1
@izzyMachado questo tipo di linguaggio nei documenti in genere significa che si riservano il "diritto" in base al contratto dell'interfaccia di analizzare, disinfettare o canonizzare la stringa di input. cioè potrebbe non essere andata e ritorno e comunque confrontare, ==ma piuttosto essere la rappresentazione "più vicina" o "migliore" che possono fare. Il destinatario in questo caso è l' NSStringimplementazione della classe e il valore restituito non è un oggetto Objective-C, quindi potrebbero anche coprirlo con un linguaggio standard.
valore

Sai perché funziona ancora quando usiamo initWithUTF8String e la stringa include caratteri non utf8, come è ancora in grado di usare la stringa (se è di menta UTF-8) e stamparla una volta che diventa una NSString?
Julian00

21
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];

questo rende NSString UTF8? o quale codifica sarebbe la NSString?
Julian00

14

Apple ora ha un nuovo modo in cui vogliono che tu esegua questa conversione. In XCode7, ho usato l'opzione Modifica> Converti> Alla sintassi C dell'obiettivo moderno ... per scoprirlo. Utilizza un simbolo di abbreviazione @.

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

3

Ho anche scoperto che:

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

Funziona come un campione.


3
È abbastanza pericoloso e non è garantito che funzioni. standardString se std :: string, è un oggetto C ++. Gli oggetti C ++ non sono sicuri per il passaggio a funzioni variadiche (i modelli variadici risolvono questo problema in C ++ 11). Se funziona è un colpo di fortuna e quasi tutti i compilatori ti avvertiranno per lo meno di non farlo (se non è un errore per cominciare).
Vitali

3

Ecco lo snippet di codice / esempio:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.