2009-03-12 17 views
157
NSString *aNSString; 
CFStringRef aCFString; 
aCFString = CFStringCreateWithCString(NULL, [aNSString UTF8String], NSUTF8StringEncoding); 
aCFString = CFXMLCreateStringByUnescapingEntities(NULL, aCFString, NULL); 

¿Cómo puedo obtener un nuevo NSString de aCFString?Cómo convertir CFStringRef a NSString?

Respuesta

331

NSString y CFStringRef son "sin conexión de puente", lo que significa que simplemente puede encasillar entre ellos.

Por ejemplo:

CFStringRef aCFString = (CFStringRef)aNSString; 

funciona perfectamente y de forma transparente. Del mismo modo:

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 también. La cuestión clave a tener en cuenta es que CoreFoundation a menudo devolverá objetos con recuentos de referencia de +1, lo que significa que deben ser liberados (todas las funciones de formato de creación de CF [Type] lo hacen).

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

+85

Si está utilizando ARC, la nueva sintaxis de fundición para este caso está ahora NSString * aNSString = (__bridge NSString *) aCFString – MikeG

+6

Gracias MikeG, que tenía que hacer similar para la conversión inversa: NSString * str = @ "a B C"; 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. –

12

son equivalentes, lo que sólo puede emitir el CFStringRef:

NSString *aNSString = (NSString*)aCFString; 

Para obtener más información, ver Toll-Free Bridged Types.

3

Añadiré que no solo se puede pasar de CFString a NSString con solo un modelo, sino que también funciona de la otra manera. Puede soltar el mensaje CFStringCreateWithCString, que es una cosa menos que necesita lanzar más tarde. (CF utiliza Create donde cacao utiliza alloc, por lo que en cualquier caso, se habría necesitado para liberarlo.)

El código resultante:

NSString *escapedString; 
NSString *unescapedString = [(NSString *) CFXMLCreateStringByUnescapingEntities(NULL, (CFStringRef) escapedString, NULL) autorelease]; 
4

En realidad, no se debe utilizar cacao retener, liberar, autorelease en los objetos de Core Foundation en general. Si está utilizando Garbage Collection (solo en Mac OS X por ahora), las llamadas de retención, liberación y liberación automática no son operativas. Por lo tanto, las pérdidas de memoria.

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

Es importante tener en cuenta la asimetría entre la Fundación Core y cacao en retener, liberar y autorelease hay-ops. Si, por ejemplo, se han equilibrado un CFCreate ... con la liberación o autorelease, se le escape el objeto en un entorno de recogida 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 previamente retenidas utilizando retener resultará en un error de subdesbordamiento de recuento de referencia.


PD: parece que no puede hacer comentarios sobre la respuesta de Peter Hosey - lo siento por la adición de mi propio innecesariamente.

2

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

CFStringRef cfstringRef = (__bridge_retained CFStringRef)aNsString; 
0

Hay que echarlo:

CFStringRef CFstringFileName=(__bridge CFStringRef)NSstringFileName; 
14

Si está utilizando ARC en las últimas versiones de Mac OS X/Objective C, es verdadera fácil:

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

Sin embargo, Xcode estará encantado de advertirle cuando intente llamar gratis al puente CFString a NSString y ofrezca envolverlo automáticamente en CFBridgingRelease(), que puede aceptar y dejar que inserte automáticamente el contenedor si hace clic en la opción.

+1

No estoy seguro, pero creo que '(__bridge NSString *)' es suficiente: no tiene sentido aumentar el conteo de retención con 'CFBridgingRelease()'. –

-3

Puede usar: Con CFStringRef idc;

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