Як перетворити std :: string в NSString?


97

Привіт, я намагаюся перетворити стандарт std::stringна, NSStringале мені не дуже долі.

Я можу успішно конвертувати з NSStringа 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 =" Голлівуд "; ' рядок.
Володимир

Відповіді:


111

Витягніть c-string з std :: string для перетворення:

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

Це, здається, не є гарною відповіддю, оскільки документація говорить: / * Кодування, залежне від користувача, значення якого походить від мови за замовчуванням користувача та, можливо, інших факторів. Використання цього кодування іноді може знадобитися при інтерпретації документів користувача з невідомими кодуваннями за відсутності інших підказок. Це кодування слід використовувати рідко, якщо воно взагалі є. Зауважте, що деякі потенційні значення тут можуть призвести до несподіваних перетворень кодування навіть досить прямого контенту NSString --- наприклад, розділових знаків з двонаправленим кодуванням. * /
cyrilchampier

30
[NSString stringWithUTF8String: mystring.c_str ()] здається більш доцільним, оскільки стд :: строка швидше виходить з вашого власного коду, який, ймовірно, в UTF8.
cyrilchampier

Чи знаєте ви, чому тут ( developer.apple.com/documentation/foundation/nsstring/… ) написано: "Повернений об'єкт може відрізнятися від оригінального приймача"? Що це означає і як би ми знали, якщо це інакше?
isJulian00

@cyrilchapier що робити, якщо наш .mm файл говорить "не вказано конкретного кодування"?
isJulian00

53

По-перше, ви повинні використовувати Objective-C ++ для цього, щоб працювати якнайменше; найпростіший спосіб забезпечити перейменування всіх ваших *.mфайлів у*.mm

На сьогоднішній день найбільш корисним (непридатним) ручним способом введення C ++ std::stringв an NSStringє:

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

Це працюватиме в більшості випадків - і якщо ви не робите конкретного виявлення та перетворення кодування, UTF-8 дасть вам хороший результат за те, що не латинські символи "просто працюють".

Якщо ви робите більшу програму або ви не єдиний, хто працює над цим, ви, мабуть, захочете щось легше застосувати.

Адаптовано з архівів розсилки какао-розробок

@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
Це rad, і я використовував його в декількох проектах iphone. Одне, що я зауважив, це те, що якщо я запускав тестові рамки Apple, і я тестував бібліотеку, яка використовує ці методи, я повинен був включати файл, що містить методи перетворення рядків, як один із "джерел компіляції" в "фази збірки" для одиничне випробування. Дивно.
Девід

1
Так, одиничний тест - це, власне, невелика програма, і він повинен мати доступ до того ж коду. Також kudos для фактичного написання тестів ;-)
оцінюйте

1
Чи знаєте ви, чому тут ( developer.apple.com/documentation/foundation/nsstring/… ) написано: "Повернений об'єкт може відрізнятися від оригінального приймача"? Що це означає і як би ми знали, якщо це інакше?
isJulian00

1
@izzyMachado така мова в документах, як правило, означає, що вони зберігають "право" за договором інтерфейсу для розбору, санітарії або кананізації вхідного рядка. тобто воно не може бути зворотним і все-таки порівнювати, ==а скоріше бути або "найближчим", або "найкращим" представленням, яке вони можуть скласти. Одержувач у цьому випадку є реалізацією NSStringкласу, і повернене значення не є об'єктом Objective-C, тому вони також можуть охоплювати це якоюсь стандартною мовою.
оцінити

Чи знаєте ви, чому це все ще працює, коли ми використовуємо initWithUTF8String, і рядок містить символи, які не містять utf8, як це все ще може використовувати рядок (якщо це м'ята UTF-8) та роздрукувати її, як тільки вона стане NSString?
isJulian00


14

Зараз у Apple є новий спосіб, коли вони хочуть, щоб ви перетворили цю конверсію. У XCode7 я використав параметр Правка> Перетворити> в сучасний синтаксис C об'єкта ..., щоб дізнатися це. Він використовує скорочений символ @.

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.