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?
retain
ing et release
-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:
__bridge
transfère un pointeur entre Objective-C et Core Foundation sans transfert de propriété.
__bridge_retained
ouCFBridgingRetain
jette un pointeur Objective-C vers un pointeur Core Foundation et vous transfère également la propriété. Vous êtes responsable d'appeler CFRelease ou une fonction associée pour renoncer à la propriété de l'objet.
__bridge_transfer
ouCFBridgingRelease
déplace un pointeur non-Objective-C vers Objective-C et transfère également la propriété à l'ARC. ARC est responsable de renoncer à la propriété de l'objet.
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 en CFString
utilisant un __bridge_retained
cast, de sorte que vous possédiez l'objet et que vous deviez le libérer explicitement en utilisant CFRelease
.
Pour conclure, vous pouvez avoir
// 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
, nous devrions utiliser __bridge
. mais quand CFString->NSString
, nous devrions utiliser __bride_transfer
. ? Et tout effet secondaire, si nous utilisons CFRelease
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 un NULL
pointeur.
CFStringRef foo (__bridge CFStringRef)theNSString;
etNSString *bar = (__bridge NSString *)theCFString;