Próbuję zrozumieć prawidłowy sposób uzyskiwania odpowiedzi NSString
z CFStringRef
ARC? To samo dotyczy jazdy w przeciwnym kierunku, CFStringRef
do NSString
ARC?
Jaki jest właściwy sposób, aby to zrobić bez tworzenia wycieków pamięci?
Próbuję zrozumieć prawidłowy sposób uzyskiwania odpowiedzi NSString
z CFStringRef
ARC? To samo dotyczy jazdy w przeciwnym kierunku, CFStringRef
do NSString
ARC?
Jaki jest właściwy sposób, aby to zrobić bez tworzenia wycieków pamięci?
CFStringRef foo (__bridge CFStringRef)theNSString;
iNSString *bar = (__bridge NSString *)theCFString;
retain
nia irelease
-ing obiektów, musimy teraz używać „piękne” jak odlewy__bridge_transfer
,__unsafe_unretained
i__autoreleasing
. Nikt nie ma na to czasu. (A poważnie, trudniej go czytać. Moim zdaniem w ogóle nie ułatwiło to zarządzania pamięcią.)Odpowiedzi:
Zwykle
NSString *yourFriendlyNSString = (__bridge NSString *)yourFriendlyCFString;
i
CFStringRef yourFriendlyCFString = (__bridge CFStringRef)yourFriendlyNSString;
Teraz, jeśli chcesz wiedzieć, dlaczego
__bridge
jest tam słowo kluczowe, możesz zapoznać się z dokumentacją Apple . Znajdziesz tam:Co oznacza, że w powyższych przypadkach rzucasz obiekt bez zmiany właściciela. Oznacza to, że w żadnym przypadku nie będziesz odpowiedzialny za obsługę pamięci ciągów.
Może się również zdarzyć, że z jakiegoś powodu zechcesz przenieść własność.
Weźmy na przykład następujący fragment
- (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 }
w takim przypadku możesz zechcieć zapisać
CFRelease
, przenosząc własność podczas przesyłania.- (void)sayHi { CFStringRef str = CFStringCreateWithCString(NULL, "Hello World!", kCFStringEncodingMacRoman); NSString * aNSString = (__bridge_transfer NSString *)str; // or alternatively NSString * aNSString = (NSString *)CFBridgingRelease(str); NSLog(@"%@", aNSString); }
Własność
str
została przeniesiona, więc teraz ARC włączy się i zwolni pamięć.Z drugiej strony możesz rzutować a
NSString *
na zaCFString
pomocą__bridge_retained
rzutowania, dzięki czemu będziesz właścicielem obiektu i będziesz musiał jawnie zwolnić go za pomocąCFRelease
.Aby to zakończyć, możesz mieć
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;
źródło
NSString->CFString
powinniśmy użyć__bridge
. ale kiedyCFString->NSString
powinniśmy użyć__bride_transfer
. ? I każdy efekt uboczny, jeśli używamy,CFRelease
gdy nie potrzebujemy. dzięki :)CFRelease
powinien rozsądnie zawiesić twój program, ponieważ skończysz z niedopasowaną operacją zatrzymania / zwolnienia, ostatecznie zwalniającNULL
wskaźnik.