Как преобразовать std :: string в NSString?


97

Привет, я пытаюсь преобразовать стандарт std::stringв формат, NSStringно мне не очень везет.

Я могу успешно преобразовать из NSStringa std::stringв следующий код

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

Однако я получаю ошибку времени компиляции, когда пытаюсь выполнить следующее

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

Я получаю ошибку

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

Я что-то упустил?

Заранее спасибо.


4
Вероятно, это опечатка, но вам не хватает символа @ для строкового литерала в 'NSString * realm = "Hollywood";' линия.
Владимир

Ответы:


111

Получить c-строку из std :: string для преобразования:

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

Это не кажется хорошим ответом, поскольку в документации говорится: / * Пользовательская кодировка, значение которой определяется языком пользователя по умолчанию и, возможно, другими факторами. Использование этой кодировки иногда может потребоваться при интерпретации пользовательских документов с неизвестными кодировками при отсутствии других подсказок. Эта кодировка должна использоваться редко, если вообще. Обратите внимание, что некоторые потенциальные значения здесь могут привести к неожиданным преобразованиям кодирования даже довольно простого содержимого NSString - например, знаков пунктуации с двунаправленным кодированием. * /
cyrilchampier 04

31
[NSString stringWithUTF8String: mystring.c_str ()] кажется более подходящим, поскольку std :: string, скорее всего, исходит из вашего собственного кода, который, скорее всего, находится в UTF8.
cyrilchampier

Вы, ребята, знаете, почему здесь ( developer.apple.com/documentation/foundation/nsstring/… ) написано: «Возвращенный объект может отличаться от исходного получателя»? Что это значит и как мы узнаем, что это другое?
isJulian00 06

@cyrilchapier, а что, если в нашем файле .mm написано «не указана конкретная кодировка»?
isJulian00 06

54

Во-первых, вы должны использовать Objective-C ++, чтобы это хоть немного работало; самый простой способ убедиться, что переименовать все ваши *.mфайлы в*.mm

Безусловно, наиболее удобный (не устаревший) способ вручную вставить C ++ std::stringв C ++ - NSStringэто:

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

Это будет работать в большинстве случаев - и если вы не выполняете определенное определение и преобразование кодировки, UTF-8 даст вам хороший результат, если нелатинские символы «просто работают».

Однако, если вы создаете более крупное приложение или не единственный, кто работает над ним - вам, вероятно, понадобится что-то более простое в применении.

Адаптировано из архивов списков рассылки 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

Имея это на месте (и соответствующим образом #importредактируя), теперь вы можете:

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

И то же самое для std::wstring, что более чем удобно.


1
Это здорово, и я использовал его в нескольких проектах для iphone. Одна вещь, которую я заметил, заключалась в том, что если я запускал платформу модульного тестирования Apple и тестировал библиотеку, которая использует эти методы, мне приходилось включать файл, содержащий методы преобразования строк, в качестве одного из «источников компиляции» в «этапах сборки» для модульный тест. Странно.
David

1
Да, модульный тест - это, по сути, его собственная небольшая программа, и она должна иметь доступ к тому же коду. Кроме того, спасибо за написание тестов ;-)
rvalue

1
Вы, ребята, знаете, почему здесь ( developer.apple.com/documentation/foundation/nsstring/… ) написано: «Возвращенный объект может отличаться от исходного получателя»? Что это значит и как мы узнаем, что это другое?
isJulian00 06

1
@izzyMachado такой язык в документах обычно означает, что они оставляют за собой «право» по контракту интерфейса на синтаксический анализ, дезинфекцию или канонизацию входной строки. т.е. это может быть не обратный путь и сравнение, ==а скорее либо «самое близкое», либо «лучшее» представление, которое они могут сделать. Получателем в этом случае является NSStringреализация класса, а возвращаемое значение не является объектом Objective-C, поэтому они также могут покрывать это с помощью некоторого стандартного языка.
rvalue

Знаете ли вы, почему это все еще работает, когда мы используем initWithUTF8String, а строка содержит символы, отличные от utf8, как он все еще может использовать строку (если это мятный UTF-8) и распечатать ее, когда она станет NSString?
isJulian00 07


14

У Apple теперь есть новый способ, которым они хотят, чтобы вы сделали это преобразование. В XCode7 я использовал опцию Edit> Convert> To Modern Objective C Syntax ..., чтобы выяснить это. Он использует сокращенный символ @.

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

3

Я также обнаружил, что:

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

Работает как чемпион.


3
Это довольно небезопасно и не гарантирует работы. standardString, если std :: string, является объектом C ++. Объекты C ++ небезопасны для перехода к вариативным функциям (вариативные шаблоны решают эту проблему в C ++ 11). Если это сработает, то это случайность, и почти каждый компилятор, по крайней мере, предупредит вас об этом (если это не ошибка).
Виталий

3

Вот фрагмент / пример кода:

string str_simple = "HELLO WORLD";

//string to NSString
NSString *stringinObjC = [NSString stringWithCString:str_simple.c_str()
                                encoding:[NSString defaultCStringEncoding]];            
NSLog(stringinObjC);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.