Estou tentando entender a maneira correta de obter um NSString
de a CFStringRef
no ARC. O mesmo para ir na direção oposta, CFStringRef
para NSString
no ARC?
Qual é a maneira correta de fazer isso sem criar vazamentos de memória?
Estou tentando entender a maneira correta de obter um NSString
de a CFStringRef
no ARC. O mesmo para ir na direção oposta, CFStringRef
para NSString
no ARC?
Qual é a maneira correta de fazer isso sem criar vazamentos de memória?
retain
ing e release
-ing objetos, devemos usar moldes "bonitos" como __bridge_transfer
, __unsafe_unretained
e __autoreleasing
. Ninguém não tem tempo para isso. (E,
Respostas:
Tipicamente
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
e
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Agora, se você quiser saber por que a __bridge
palavra-chave está lá, consulte a documentação da Apple . Lá você encontrará:
__bridge
transfere um ponteiro entre Objective-C e Core Foundation sem transferência de propriedade.
__bridge_retained
ouCFBridgingRetain
converte um ponteiro Objective-C em um ponteiro Core Foundation e também transfere a propriedade para você. Você é responsável por chamar CFRelease ou uma função relacionada para abrir mão da propriedade do objeto.
__bridge_transfer
ouCFBridgingRelease
move um ponteiro não Objective-C para Objective-C e também transfere a propriedade para ARC. A ARC é responsável por renunciar à propriedade do objeto.
O que significa que nos casos acima você está lançando o objeto sem alterar a propriedade. Isso significa que, em nenhum dos casos, você será responsável pelo manuseio da memória das cordas.
Também pode haver o caso em que você deseja transferir a propriedade por algum motivo.
Por exemplo, considere o seguinte snippet
- (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
}
em tal caso, você pode querer salvar um CFRelease
transferindo a propriedade ao lançar.
- (void)sayHi {
CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman);
NSString * aNSString = (__bridge_transfer NSString *)str;
// or alternatively
NSString * aNSString = (NSString *)CFBridgingRelease(str);
NSLog(@"%@", aNSString);
}
A propriedade de str
foi transferida, então agora o ARC entrará em ação e liberará a memória para você.
Por outro lado, você pode converter um NSString *
em um CFString
usando um __bridge_retained
elenco, de modo que você será o proprietário do objeto e terá que liberá-lo explicitamente usando CFRelease
.
Para finalizar você pode ter
// 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
, devemos usar __bridge
. mas quando CFString->NSString
, devemos usar __bride_transfer
. ? E qualquer efeito colateral, se usarmos CFRelease
quando não precisarmos também. obrigado :)
CFRelease
deve travar razoavelmente seu programa, já que você terminará com uma operação de retenção / liberação incompatível, eventualmente liberando um NULL
ponteiro.
CFStringRef foo (__bridge CFStringRef)theNSString;
eNSString *bar = (__bridge NSString *)theCFString;