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?
retain
ing y release
-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á:
__bridge
transfiere un puntero entre Objective-C y Core Foundation sin transferencia de propiedad.
__bridge_retained
oCFBridgingRetain
lanza un puntero de Objective-C a un puntero de Core Foundation y también le transfiere la propiedad. Usted es responsable de llamar a CFRelease o una función relacionada para renunciar a la propiedad del objeto.
__bridge_transfer
oCFBridgingRelease
mueve un puntero que no es de Objective-C a Objective-C y también transfiere la propiedad a ARC. ARC es responsable de renunciar a la propiedad del objeto.
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 *
a CFString
usando un __bridge_retained
yeso, de modo que serás dueño del objeto y tendrás que liberarlo explícitamente usando CFRelease
.
Para envolverlo puedes tener
// 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`
// 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;
NSString->CFString
, deberíamos usar __bridge
. pero cuando CFString->NSString
deberíamos usar __bride_transfer
. ? Y cualquier efecto secundario, si lo usamos CFRelease
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á un NULL
puntero.
CFStringRef foo (__bridge CFStringRef)theNSString;
yNSString *bar = (__bridge NSString *)theCFString;