¿Cómo convertir CFStringRef a NSString?

169
NSString *aNSString;
CFStringRef aCFString;
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding);
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL);

¿Cómo puedo obtener una nueva NSStringa partir de aCFString?

papr
fuente

Respuestas:

349

NSString y CFStringRef son "Toll free bridged", lo que significa que puede simplemente escribir entre ellos.

Por ejemplo:

CFStringRef aCFString = (CFStringRef)aNSString;

Funciona perfectamente y de forma transparente. Igualmente:

NSString *aNSString = (NSString *)aCFString;

La sintaxis anterior era para MRC. Si está utilizando ARC, la nueva sintaxis de conversión es la siguiente:

NSString *aNSString = (__bridge NSString *)aCFString;

funciona igual de bien La cuestión clave a tener en cuenta es que CoreFoundation a menudo devolverá objetos con recuentos de referencia +1, lo que significa que deben liberarse (todas las funciones de formato CF [Type] Create hacen esto).

Lo bueno es que en Cocoa puedes usar de forma segura la liberación automática o liberar para liberarlos.

NilObject
fuente
88
Si está utilizando ARC, la nueva sintaxis de conversión para este caso ahora es NSString * aNSString = (__bridge NSString *) aCFString
MikeG
66
Gracias MikeG, tuve que hacer algo similar para la conversión inversa: NSString * str = @ "abc"; CFStringRef cstrref = (__ bridge CFStringRef) str;
KomodoDave
2
@NilObject, actualice su respuesta para incluir ARC para que los buscadores no tengan que verificar los comentarios. Gracias.
Dan Rosenstark
17

Si está utilizando ARC en versiones recientes de Mac OS X / Objective C, es realmente fácil:

NSString *happyString = (NSString *)CFBridgingRelease(sadString);

Sin embargo, Xcode le avisará con gusto cuando intente llamar sin cargo el puente CFString a NSString y le ofrecerá envolverlo automáticamente en CFBridgingRelease (), que puede aceptar y dejar que inserte automáticamente el contenedor si hace clic en la opción.

luz clara
fuente
3
No estoy seguro, pero creo que (__bridge NSString *)es suficiente: no tiene sentido aumentar el conteo de retención CFBridgingRelease().
Cœur
12

Son equivalentes, por lo que puede lanzar CFStringRef:

NSString *aNSString = (NSString*)aCFString;

Para obtener más información, consulte Tipos de puente gratuitos .

Martin Cote
fuente
4

En realidad, no debe utilizar la retención, liberación y liberación automática de Cocoa en los objetos de Core Foundation en general. Si está utilizando Garbage Collection (solo en Mac OS X por el momento), las llamadas de retención, liberación y liberación automática no son operativas. De ahí la pérdida de memoria.

De Apple http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/GarbageCollection/Articles/gcCoreFoundation.html :

Es importante apreciar la asimetría entre Core Foundation y Cocoa, donde la retención, la liberación y la liberación automática no son operacionales. Si, por ejemplo, ha equilibrado un CFCreate ... con liberación o liberación automática, filtrará el objeto en un entorno de recolección de basura:

NSString *myString = (NSString *)CFStringCreate...(...);
// do interesting things with myString...
[myString release]; // leaked in a garbage collected environment

Por el contrario, el uso de CFRelease para liberar un objeto que haya retenido previamente usando retener dará como resultado un error de desbordamiento del recuento de referencia.


PD: parece que no puedo comentar la respuesta de Peter Hosey, perdón por agregar la mía innecesariamente.

gavinbeatty
fuente
3

Agregaré que no solo puede pasar de CFString a NSString con solo un tipo de conversión, sino que también funciona a la inversa. Puede soltar el CFStringCreateWithCStringmensaje, que es una cosa menos que necesita publicar más tarde. (La CF se usa Createdonde usa Cocoa alloc, por lo que, de cualquier manera, habría necesitado liberarla).

El código resultante:

NSString *escapedString;
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease];
Peter Hosey
fuente
2

Estaba teniendo un problema con ARC y el conteo retenido de CFStrings. Usar la respuesta de NilObjects con un ligero ajuste funcionó perfectamente para mí. Acabo de agregar retenido por ejemplo.

CFStringRef cfstringRef = (__bridge_retained  CFStringRef)aNsString;
dloomb
fuente
0

Tienes que lanzarlo:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName;
Vincent
fuente
-3

Puede usar: Con CFStringRef idc;

NSString *sId = [NSString stringWithFormat:@"%@", (NSString*)idc];
vualoaithu
fuente