Próbuję zrozumieć prawidłowy sposób uzyskiwania odpowiedzi NSStringz CFStringRefARC? To samo dotyczy jazdy w przeciwnym kierunku, CFStringRefdo NSStringARC?
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 NSStringz CFStringRefARC? To samo dotyczy jazdy w przeciwnym kierunku, CFStringRefdo NSStringARC?
Jaki jest właściwy sposób, aby to zrobić bez tworzenia wycieków pamięci?
retainnia i release-ing obiektów, musimy teraz używać „piękne” jak odlewy __bridge_transfer, __unsafe_unretainedi __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 __bridgejest tam słowo kluczowe, możesz zapoznać się z dokumentacją Apple . Znajdziesz tam:
__bridgeprzenosi wskaźnik między Objective-C i Core Foundation bez przenoszenia prawa własności.
__bridge_retainedlubCFBridgingRetainrzuca 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_transferlubCFBridgingReleaseprzenosi 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ść strzostała przeniesiona, więc teraz ARC włączy się i zwolni pamięć.
Z drugiej strony możesz rzutować a NSString *na za CFStringpomocą __bridge_retainedrzutowania, 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->CFStringpowinniśmy użyć __bridge. ale kiedy CFString->NSStringpowinniśmy użyć __bride_transfer. ? I każdy efekt uboczny, jeśli używamy, CFReleasegdy nie potrzebujemy. dzięki :)
CFReleasepowinien rozsądnie zawiesić twój program, ponieważ skończysz z niedopasowaną operacją zatrzymania / zwolnienia, ostatecznie zwalniając NULLwskaźnik.
CFStringRef foo (__bridge CFStringRef)theNSString;iNSString *bar = (__bridge NSString *)theCFString;