NSString to CFStringRef i CFStringRef to NSString w ARC?


87

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?


4
CFStringRef foo (__bridge CFStringRef)theNSString;iNSString *bar = (__bridge NSString *)theCFString;

Czy mógłbyś szczegółowo wyjaśnić, co naprawdę się dzieje, gdy używane są te dwie opcje?
— zumzum

Nie do końca. Nie używam ARC, więc wiem tylko, że musisz to zrobić, ale nie wiem dlaczego.

1
@GabrielePetronella ARC miał na celu ułatwienie kodowania, skrócenie i czytelność kodu oraz zmniejszenie możliwości błędów ludzkich. Więc teraz, zamiast zająć się liczy odniesienia przez 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ą.)

1
@ H2CO3 dziękuję za odpowiedź. Zdecydowanie się nie zgadzam, szczególnie z ostatnim zdaniem, ale szanuję Twój punkt widzenia :)
— Gabriele Petronella

Odpowiedzi:


177

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:

__bridge przenosi wskaźnik między Objective-C i Core Foundation bez przenoszenia prawa własności.

__bridge_retainedlub CFBridgingRetainrzuca 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_transferlub CFBridgingReleaseprzenosi 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ć

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;

Bardzo dziękuję, to nie jest tak naprawdę intuicyjne, ale dzięki tobie lekcja wyciągnięta
— Sulfkain

@: małe pytanie. więc jeśli używamy ARC. kiedy 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 :)
— hqt

@hqt, jeśli chcesz „łatwego” sposobu, tak, to, co mówisz, jest poprawne. Ponadto, dodatkowy CFReleasepowinien rozsądnie zawiesić twój program, ponieważ skończysz z niedopasowaną operacją zatrzymania / zwolnienia, ostatecznie zwalniając NULLwskaźnik.
— Gabriele Petronella
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.