Z ARC, już nie mogę rzucić CGColorRef
się id
. Dowiedziałem się, że muszę wykonać obsadę z mostkiem. Według clang Docs :
Bridged obsada jest oddanych C-styl opatrzone jednym z trzech słów kluczowych:
(__bridge T) op
rzutuje operand na typ docelowyT
. JeśliT
jest typem wskaźnika obiektu, który można przechowywać, toop
musi mieć typ wskaźnika, którego nie można przechowywać. JeśliT
jest nieprzechowywalnym typem wskaźnika, to op musi mieć możliwy do utrzymania typ wskaźnika obiektu. W przeciwnym razie odlew jest źle uformowany. Nie ma przeniesienia własności, a ARC nie wprowadza żadnych operacji zachowania.
(__bridge_retained T) op
rzutuje operand, który musi mieć typ wskaźnika obiektu, który można zachować, na typ docelowy, który musi być typem wskaźnika, którego nie można zachować. ARC zachowuje wartość, z zastrzeżeniem zwykłych optymalizacji wartości lokalnych, a odbiorca jest odpowiedzialny za zbilansowanie tego +1.
(__bridge_transfer T) op
rzutuje operand, który musi mieć nieprzechowywalny typ wskaźnika, na typ docelowy, który musi być zachowanym typem wskaźnika obiektu. ARC zwolni wartość na końcu otaczającego pełnego wyrażenia, z zastrzeżeniem zwykłych optymalizacji wartości lokalnych.Rzuty te są wymagane do przenoszenia obiektów do i poza kontrolę ARC; zobacz uzasadnienie w sekcji dotyczącej konwersji zachowywalnych wskaźników obiektów.
Używanie odlewu
__bridge_retained
lub__bridge_transfer
wyłącznie do przekonania ARC do emitowania odpowiednio niezrównoważonego zatrzymania lub uwolnienia jest kiepską formą.
W jakich sytuacjach użyłbym każdego z nich?
Na przykład CAGradientLayer
ma colors
właściwość, która akceptuje tablicę CGColorRef
s. Domyślam się, że powinienem __brige
tutaj użyć , ale dokładnie, dlaczego powinienem (lub nie powinienem), nie jest jasne.
źródło
Odpowiedzi:
Zgadzam się, że opis jest mylący. Ponieważ właśnie je zrozumiałem, spróbuję podsumować:
(__bridge_transfer <NSType>) op
lub alternatywnieCFBridgingRelease(op)
jest używany do zużywania liczby zatrzymań aCFTypeRef
podczas przesyłania jej do ARC. Może to być również reprezentowane przezid someObj = (__bridge <NSType>) op; CFRelease(op);
(__bridge_retained <CFType>) op
lub alternatywnieCFBridgingRetain(op)
jest używany do przekazaniaNSObject
lądu CF, dając mu +1 do zatrzymania. Powinieneś postępować zCFTypeRef
utworzonym w ten sposób wynikiem tak samo, jak z wynikiemCFStringCreateCopy()
. Może to być również reprezentowane przezCFRetain((__bridge CFType)op); CFTypeRef someTypeRef = (__bridge CFType)op;
__bridge
po prostu rzuca między krainą wskaźnika i ziemią obiektu-C. Jeśli nie masz ochoty korzystać z powyższych konwersji, użyj tej.Może to jest pomocne. Ja osobiście wolę
CFBridging…
makra bardziej niż zwykłe rzuty.źródło
Znalazłem inne wyjaśnienie w dokumentacji iOS, które moim zdaniem jest łatwiejsze do zrozumienia:
__bridge
przenosi wskaźnik między Objective-C i Core Foundation bez przenoszenia prawa własności.__bridge_retained (CFBridgingRetain)
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 (CFBridgingRelease)
Przenosi non-Objective-C wskaźnik do Objective-C , a także przenosi prawo własności do ARC.ARC odpowiada za zrzeczenie się własności obiektu.
Źródło: bezpłatne typy mostowe
źródło
W ramach kontynuacji, w tym konkretnym przypadku, jeśli korzystasz z systemu iOS, Apple zaleca użycie UIColor i jego
-CGColor
metody w celu zwrócenia CGColorRef do NSArraycolors
. W Transitioning to ARC Release Notes , w sekcji „The Compiler Handles CF Objects Returned From Cocoa Methods”, wskazano, że użycie metody, takiej jak-CGColor
zwracająca obiekt Core Foundation, będzie automatycznie obsługiwane przez kompilator.Dlatego sugerują użycie kodu podobnego do następującego:
Zauważ, że w tej chwili w przykładowym kodzie Apple brakuje rzutowania (id), które mam powyżej, co jest nadal konieczne, aby uniknąć błędu kompilatora.
źródło