objective c - NSString a CFStringRef y CFStringRef a NSString en ARC?
objective-c automatic-ref-counting (1)
Estoy tratando de entender la forma correcta de obtener un NSString
de un CFStringRef
en ARC? Lo mismo para ir en la dirección opuesta, CFStringRef
a NSString
en ARC?
¿Cuál es la forma correcta de hacer esto sin crear pérdidas de memoria?
Típicamente
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
y
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Ahora, si quiere saber por qué la palabra clave __bridge
está allí, puede consultar la documentación de Apple . Allí encontrarás:
__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 transfiere la propiedad a usted. 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 no-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á lanzando el objeto sin cambiar la propiedad. Esto implica que en ninguno de los casos estarás a cargo de manejar la memoria de las cuerdas.
También puede haber un caso en el 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 CFRelease
del envío.
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
La propiedad de str
ha sido transferida, por lo que ARC activará y liberará la memoria por usted.
Por otro lado, puedes convertir un NSString *
en un CFString
usando un molde __bridge_retained
, de modo que serás el propietario del objeto y tendrás que liberarlo explícitamente mediante CFRelease
.
Para concluir, 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;