J'essaie de comprendre la bonne façon d'obtenir un à NSString
partir d'un CFStringRef
ARC? Idem pour aller la direction opposée, CFStringRef
à NSString
en ARC?
Quelle est la bonne façon de procéder sans créer de fuites de mémoire?
J'essaie de comprendre la bonne façon d'obtenir un à NSString
partir d'un CFStringRef
ARC? Idem pour aller la direction opposée, CFStringRef
à NSString
en ARC?
Quelle est la bonne façon de procéder sans créer de fuites de mémoire?
CFStringRef foo (__bridge CFStringRef)theNSString;
etNSString *bar = (__bridge NSString *)theCFString;
retain
ing etrelease
-ing des objets, nous devons maintenant utiliser de "beaux" moulages comme__bridge_transfer
,__unsafe_unretained
et__autoreleasing
. Personne n'a pas le temps pour ça. (Et sérieusement, c'est plus difficile à lire. À mon avis, cela n'a pas du tout facilité la gestion de la mémoire.)Réponses:
Typiquement
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
et
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Maintenant, si vous voulez savoir pourquoi le
__bridge
mot-clé est là, vous pouvez vous référer à la documentation Apple . Vous y trouverez:Ce qui signifie que dans les cas ci-dessus, vous lancez l'objet sans en changer la propriété. Cela implique que dans aucun des cas, vous ne serez responsable de la gestion de la mémoire des chaînes.
Il se peut également que vous souhaitiez transférer la propriété pour une raison quelconque.
Par exemple, considérez l'extrait suivant
- (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 }
dans ce cas, vous souhaiterez peut-être enregistrer un
CFRelease
en transférant la propriété lors de la diffusion.- (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 propriété de
str
a été transférée, donc maintenant ARC entrera en vigueur et libérera la mémoire pour vous.À l'inverse, vous pouvez convertir un
NSString *
en un enCFString
utilisant un__bridge_retained
cast, de sorte que vous possédiez l'objet et que vous deviez le libérer explicitement en utilisantCFRelease
.Pour conclure, vous pouvez avoir
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;
la source
NSString->CFString
, nous devrions utiliser__bridge
. mais quandCFString->NSString
, nous devrions utiliser__bride_transfer
. ? Et tout effet secondaire, si nous utilisonsCFRelease
quand nous n'en avons pas besoin trop. merci :)CFRelease
devrait raisonnablement planter votre programme, car vous vous retrouverez avec une opération de conservation / libération incompatible, ce qui finira par libérer unNULL
pointeur.