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?
retain
nia i release
-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:
__bridge
przenosi wskaźnik między Objective-C i Core Foundation bez przenoszenia prawa własności.
__bridge_retained
lubCFBridgingRetain
rzuca wskaźnik Objective-C na wskaźnik Core Foundation, a także przenosi własność na Ciebie. Jesteś odpowiedzialny za wywołanie CFRelease lub powiązanej funkcji w celu zrzeczenia się własności obiektu.
__bridge_transfer
lubCFBridgingRelease
przenosi wskaźnik nie będący celem C do celu C, a także przenosi własność do ARC. ARC odpowiada za zrzeczenie się własności obiektu.
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 za CFString
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ć
// 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
powinniśmy użyć __bridge
. ale kiedy CFString->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ąc NULL
wskaźnik.
CFStringRef foo (__bridge CFStringRef)theNSString;
iNSString *bar = (__bridge NSString *)theCFString;