¿Cómo convertir std :: string a NSString?

97

Hola, estoy tratando de convertir un estándar std::stringen uno, NSStringpero no tengo mucha suerte.

Puedo convertir con éxito de an NSStringa a std::stringcon el siguiente código

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

Sin embargo, obtengo un error de tiempo de compilación cuando intento lo siguiente

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

El error que obtengo es

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

¿Me estoy perdiendo de algo?

Gracias por adelantado.

Anthony McCormick
fuente
4
Debe ser un error tipográfico, pero falta '@' para el literal de cadena en 'NSString * realm = "Hollywood";' línea.
Vladimir

Respuestas:

111

Obtenga c-string de std :: string para la conversión:

NSString *errorMessage = [NSString stringWithCString:REALM.c_str() 
                                   encoding:[NSString defaultCStringEncoding]];
Vladimir
fuente
Esta no parece ser una buena respuesta, como dice la documentación: / * Codificación dependiente del usuario cuyo valor se deriva del idioma predeterminado del usuario y potencialmente de otros factores. El uso de esta codificación a veces puede ser necesario al interpretar documentos de usuario con codificaciones desconocidas, en ausencia de otras sugerencias. Esta codificación debe usarse raramente, si es que se usa. Tenga en cuenta que algunos valores potenciales aquí pueden resultar en conversiones de codificación inesperadas incluso de contenido NSString bastante sencillo, por ejemplo, caracteres de puntuación con una codificación bidireccional. * /
cyrilchampier
30
[NSString stringWithUTF8String: mystring.c_str ()] parece más apropiado, ya que std :: string es más probable que provenga de su propio código, que probablemente esté en UTF8.
cyrilchampier
¿Saben por qué aquí ( developer.apple.com/documentation/foundation/nsstring/… ) dice "El objeto devuelto puede ser diferente del receptor original"? ¿Qué significa esto y cómo sabríamos si es diferente?
isJulian00
@cyrilchapier ¿qué pasa si nuestro archivo .mm dice "no se especificó una codificación específica"?
isJulian00
53

En primer lugar, debe utilizar Objective-C ++ para que esto funcione en lo más mínimo; La forma más sencilla de asegurarse de que es cambiar el nombre de todos sus *.marchivos a*.mm

Con mucho, la forma manual más utilizable (no obsoleta) de introducir un C ++ std::stringen un NSStringes con:

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

Esto funcionará en la mayoría de los casos, y si no está haciendo una detección y conversión de codificación específica, UTF-8 le dará un buen resultado por tener caracteres no latinos 'simplemente funcionan'.

Sin embargo, si está creando una aplicación más grande o no es el único que trabaja en ella, probablemente querrá algo que sea más fácil de aplicar.

Adaptado de los archivos de la lista de correo de 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 eso en su lugar (y debidamente #importeditado) ahora puede:

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

Y lo mismo para std::wstring, que es más que útil.

rvalue
fuente
1
Esto es genial y lo he usado en un par de proyectos de iphone. Una cosa que noté fue que si estaba ejecutando el marco de prueba unitario de Apple y estaba probando una biblioteca que utiliza estos métodos, tenía que incluir el archivo que contiene los métodos de conversión de cadenas como una de las "Fuentes de compilación" en las "Fases de compilación" para la prueba unitaria. Extraño.
David
1
Sí, la prueba unitaria es esencialmente su propio pequeño programa y necesita tener acceso al mismo código. Además, felicitaciones por escribir pruebas ;-)
rvalue
1
¿Saben por qué aquí ( developer.apple.com/documentation/foundation/nsstring/… ) dice "El objeto devuelto puede ser diferente del receptor original"? ¿Qué significa esto y cómo sabríamos si es diferente?
isJulian00
1
@izzyMachado, ese tipo de lenguaje en los documentos normalmente significa que se reservan el "derecho" bajo el contrato de interfaz para analizar, desinfectar o canonicalizar la cadena de entrada. es decir, puede que no sea de ida y vuelta y aún así se compare, ==sino que sea la representación "más cercana" o la "mejor" que puedan hacer. En este caso, el receptor es la NSStringimplementación de la clase, y el valor devuelto no es un objeto Objective-C, por lo que también podrían cubrir eso con algún lenguaje estándar.
rvalue
¿Sabes por qué esto todavía funciona cuando usamos initWithUTF8String y la cadena incluye caracteres que no son utf8? ¿Cómo puede seguir usando la cadena (si es UTF-8 perfecto) e imprimirla una vez que se convierta en una NSString?
isJulian00
21
NSString* mystring = [NSString stringWithUTF8String:stdstring.c_str()];
John Bowers
fuente
¿Esto hace que NSString UTF8? o ¿qué codificación sería NSString?
isJulian00
14

Apple ahora tiene una nueva forma en la que quieren que hagas esta conversión. En XCode7, utilicé la opción Editar> Convertir> A la sintaxis C moderna de Objective ... para averiguarlo. Utiliza un símbolo @ abreviado.

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

También encontré que:

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

Funciona como un campeón.

BadPirate
fuente
3
Eso es bastante inseguro y no se garantiza que funcione. standardString si es un std :: string, es un objeto C ++. Los objetos C ++ no son seguros para pasar a funciones variadas (las plantillas variadas resuelven este problema en C ++ 11). Si funciona, es una casualidad y casi todos los compiladores, al menos, le advertirán que no lo haga (si no es un error para empezar).
Vitali
3

Aquí está el fragmento de código / ejemplo:

string str_simple = "HELLO WORLD";

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