Jak przekonwertować NSString na std :: string?

Odpowiedzi:

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

Edycja: Po kilku latach pozwól mi rozwinąć tę odpowiedź. Jak słusznie wskazał, będziesz najprawdopodobniej chcą korzystać cStringUsingEncoding:ze NSASCIIStringEncodingjeśli masz zamiar skończyć użyciu std::string. Możesz używać UTF-8 z normalnym std::strings, ale pamiętaj, że te operują na bajtach, a nie na znakach lub nawet grafemach. Aby dobrze „zacząć”, sprawdź to pytanie i odpowiedź .

Zauważ również, że jeśli masz ciąg, który nie może być reprezentowany jako ASCII, ale nadal chcesz go w postaci std::stringi nie chcesz tam znaków innych niż ASCII, możesz użyć, dataUsingEncoding:allowLossyConversion:aby uzyskać NSDatareprezentację ciągu z kodowaniem stratnym ASCII treści, a następnie rzuć to na swój plikstd::string

JustSid
źródło
13
Uważaj na kodowanie. Chociaż UTF-8 jest ogólnie dobrym wyborem, jeśli API, z którym pracujesz, oczekuje, powiedzmy, czystego ASCII lub systemowej strony kodowej, będziesz musiał użyć -cStringUsingEncoding:zamiast tego. :)
Jonathan Grynspan
13
Jest to wyciek pamięci, jeśli go nie usuniesz, zwrócony wskaźnik nie jest policzonym obiektem odwołania Objective-C. Ogólnie należy unikać używania operatora new dla std :: string.
SiimKallas
Nie powinna to być akceptowana odpowiedź i zdecydowanie nie jest to pierwsza rzecz do rozważenia podczas wykonywania tej konwersji.
JBL
@JBL Po zaledwie 4 latach i kilku tygodniach poszedłem poszerzyć swoją odpowiedź. Mam nadzieję, że teraz jest to bardziej akceptowalne.
JustSid
@JustSid Powinienem był sprecyzować swoją opinię, ale inną kwestią jest domyślne użycie wskaźnika. W rzeczywistości współpracownik z doświadczeniem w ObjC, bez znajomości C ++, użył tego bez usuwania, co skończyło się wyciekiem pamięci. I bardziej ogólnie; dzikie zwierzęta nie newsą mile widziane, a std::shared_ptrlub std::unique_ptrpowinno być preferowane.
JBL
50

Jak zasugerował Ynau w komentarzu, w ogólnym przypadku lepiej byłoby trzymać wszystko na stosie zamiast na stercie (użycie newtworzy ciąg na stercie), stąd (zakładając kodowanie UTF8):

NSString *foo = @"Foo";
std::string bar([foo UTF8String]);
Marco83
źródło
8

Jak zauważono na philjordan.eu , może być również tak, że NSString jest nil. W takim przypadku rzut należy wykonać w następujący sposób:

// UWAGA: jeśli foo jest równe nil, to da pusty łańcuch C ++

// zamiast wyłuskiwania wskaźnika NULL z UTF8String.

Doprowadziłoby to do takiej konwersji:

NSString *foo = @"Foo";
std::string bar = std::string([foo UTF8String], [foo lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
Bruno Bieri
źródło
1
Jest to niezwykle przydatne. Martwię się, że prawie wszyscy go przeoczają. Rozbijecie się na NIL.
P i