Estoy tratando de comprender la forma correcta de conseguir una NSString
de una CFStringRef
de ARC? Lo mismo para ir en la dirección opuesta, CFStringRef
a NSString
ARC?
¿Cuál es la forma correcta de hacer esto sin crear pérdidas de memoria?
Estoy tratando de comprender la forma correcta de conseguir una NSString
de una CFStringRef
de ARC? Lo mismo para ir en la dirección opuesta, CFStringRef
a NSString
ARC?
¿Cuál es la forma correcta de hacer esto sin crear pérdidas de memoria?
CFStringRef foo (__bridge CFStringRef)theNSString;
yNSString *bar = (__bridge NSString *)theCFString;
retain
ing yrelease
-ing, ahora debemos usar moldes "hermosos" como__bridge_transfer
,__unsafe_unretained
y__autoreleasing
. Nadie no tiene tiempo para eso. (Y en serio, es más difícil de leer. En mi opinión, no facilitó la gestión de la memoria en absoluto).Respuestas:
Típicamente
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
y
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Ahora, si quiere saber por qué la
__bridge
palabra clave está ahí, puede consultar la documentación de Apple . Allí encontrará:Lo que significa que en los casos anteriores estás lanzando el objeto sin cambiar la propiedad. Esto implica que en ningún caso serás el encargado de manejar la memoria de las cadenas.
También puede darse el caso de que desee transferir la propiedad por algún motivo.
Por ejemplo, considere el siguiente fragmento
- (void)sayHi { CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman); NSString * aNSString = (__bridge NSString *)str; NSLog(@"%@", aNSString); CFRelease(str); //you have to release the string because you created it with a 'Create' CF function }
en tal caso, es posible que desee guardar un
CFRelease
transfiriendo la propiedad al transmitir.- (void)sayHi { CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman); NSString * aNSString = (__bridge_transfer NSString *)str; // or alternatively NSString * aNSString = (NSString *)CFBridgingRelease(str); NSLog(@"%@", aNSString); }
Se
str
ha transferido la propiedad de , por lo que ahora ARC se activará y liberará la memoria por usted.Por otro lado, puedes lanzar un
NSString *
aCFString
usando un__bridge_retained
yeso, de modo que serás dueño del objeto y tendrás que liberarlo explícitamente usandoCFRelease
.Para envolverlo puedes tener
NSString → CFString
// Don't transfer ownership. You won't have to call `CFRelease` CFStringRef str = (__bridge CFStringRef)string; // Transfer ownership (i.e. get ARC out of the way). The object is now yours and you must call `CFRelease` when you're done with it CFStringRef str = (__bridge_retained CFStringRef)string // you will have to call `CFRelease`
CFString → NSString
// Don't transfer ownership. ARC stays out of the way, and you must call `CFRelease` on `str` if appropriate (depending on how the `CFString` was created) NSString *string = (__bridge NSString *)str; // Transfer ownership to ARC. ARC kicks in and it's now in charge of releasing the string object. You won't have to explicitly call `CFRelease` on `str` NSString *string = (__bridge_transfer NSString *)str;
fuente
NSString->CFString
, deberíamos usar__bridge
. pero cuandoCFString->NSString
deberíamos usar__bride_transfer
. ? Y cualquier efecto secundario, si lo usamosCFRelease
cuando no lo necesitamos. gracias :)CFRelease
debería bloquear razonablemente su programa, ya que terminará con una operación de retención / liberación no coincidente, y eventualmente liberará unNULL
puntero.