W Swift widzę kilka metod, takich jak:
@objc private func doubleTapGestureRecognized(recognizer: UITapGestureRecognizer)
Zastanawiałem się, kiedy używać @objc? Czytałem niektóre dokumenty, ale mówią, że jeśli chcesz, aby było możliwe wywołanie w Objective-C, powinieneś dodać flagę @objc
Jest to jednak funkcja prywatna w języku Swift. Co robi @obj?
Odpowiedzi:
prywatny oznacza, że jest widoczny tylko w języku Swift. więc użyj @objc, aby zobaczyć w Objective-C. Jeśli masz funkcję szybkiego wybierania funkcji prywatnej, jest to wymagane.
Zobacz: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithObjective-CAPIs.html
źródło
@objc private func doubleTapGestureRecognized
co mieć zarówno @objc, jak i prywatne? Czy mówisz, że klasy Objective-C mogą nadpisywać doubleTapGestureRecognized?Kolejna późna odpowiedź, ale żadna z istniejących odpowiedzi na to pytanie tak naprawdę nie odpowiada na pytanie PO, a mianowicie: dlaczego do cholery miałbyś używać
@objc
naprivate
członku klasy, jeśli@objc
istnieje do interakcji z celem-C i tym członkiem jest prywatny, co oznacza, że nawet jeśli masz kod Objective-C w swoim projekcie, i tak nie powinien on widzieć członka?Powodem jest to, że ponieważ wiele frameworków jest napisanych w Objective-C, czasami funkcje Objective-C są potrzebne do interakcji z niektórymi API.
Na przykład załóżmy, że chcę zarejestrować się w celu otrzymania powiadomienia przez
DistributedNotificationCenter
:DistributedNotificationCenter.default.addObserver(self, selector: #selector(somethingHappened(_:)), name: someNotification, object: nil)
Aby to zadziałało, musimy być w stanie uzyskać selektor dla
somethingHappened
metody. Jednak selektory są koncepcją Objective-C, więc jeśli metoda nie jest widoczna dla Objective-C, nie ma selektora. Dlatego, nawet jeśli metoda jest prywatna i nie powinna być wywoływana przez dowolnego kodu z zewnątrz, to będzie potrzebować@objc
, aby dlaDistributedNotification
kodu, który jest napisany w Objective-C, aby móc nazwać go za pomocą selektora.Innym częstym przypadkiem, w którym
@objc
jest to potrzebne, jest obsługa kodowania klucz-wartość (KVC), szczególnie w systemie macOS, gdzie KVC i KVO są używane do implementacji powiązań kakao. KVC, podobnie jak wiele innych systemów w kakao, jest zaimplementowane w Objective-C, co powoduje, że właściwości zgodne z KVC muszą być widoczne w środowisku wykonawczym Objective-C. Czasami ma sens, aby właściwości zgodne z KVC były prywatne. Jednym z przykładów jest sytuacja, gdy masz właściwość, która wpływa na inne właściwości:@objc private dynamic var originalProperty: String @objc private static let keyPathsForValuesAffectingDependentProperty: Set<String> = [ #keyPath(originalProperty) ] @objc public var dependentProperty: String { return changeItSomehow(self.originalProperty) }
W tym przypadku nasz rzeczywisty majątek przechowywany jest prywatny, ale własnością zależne, które nie narazić się do kodu zewnętrznego, musi wysłać swoje powiadomienia, gdy prywatna własność jest aktualizowana. Oznaczając własność prywatną jako
@objc
, możemy to łatwo zrobić, konfigurując zależność KVC - w przeciwnym razie musielibyśmy napisać kod, aby ręcznie wysyłać powiadomienia w właściwościach prywatnychwillSet
ididSet
programach obsługi. Ponadto właściwość statyczna, która informuje system KVC, od któregodependentProperty
jest zależny,originalProperty
musi być ujawniona Objective-C, aby system KVC i go znaleźć i wywołać, ale nie jest to istotne dla klientów naszego kodu.Ponadto kontroler widoku w aplikacji macOS, który aktualizuje formanty w swoim widoku przy użyciu powiązań Cocoa jako szczegółów implementacji, może sprawić, że niektóre właściwości prywatne będą zgodne z KVC w celu powiązania z nimi tych formantów.
Jak widać, są chwile, kiedy metoda lub właściwość może wymagać ujawnienia Objective-C w celu interakcji z platformami, bez konieczności bycia widoczną dla klientów kodu.
źródło
@objc / dynamic
Chodzi o kompatybilność: po zaimportowaniu pliku / kodu Swift do projektu opartego na Objective-C.
I użyj tego, jeśli chcesz, aby Twoja właściwość / metoda była dostępna za pomocą kodu lub klasy Objective-C.
W większości przypadków dzieje się tak, gdy tworzysz podklasę klasy Swift klasy bazowej Objective-C.
Tutaj dokumentacja Apple, która mówi o
@objc
.Używanie Swift z Objective-C
Zgodność z językami
Zaktualizowano linki:
Wygląda na to, że linki zostały zaktualizowane przez firmę Apple.
źródło
@objc jest atrybutem klasy, więc używasz
@objc public class MyClass
Udostępnia metody klasy klasom Objective C, więc będziesz go używać tylko wtedy, gdy twoja klasa zawiera funkcje publiczne
źródło
Późna odpowiedź, ale to
@objc
zachowanie zmienia się nieznacznie od wersji Swift 4 (która pojawiła się w Xcode 9, która została ogólnie wydana 10 dni temu).W Swift 4
@objc
usunięto niektóre przypadki wnioskowania . Oznacza to po prostu w niektórych dodatkowych przypadkach, gdy przed@objc
wywnioskowaniem nagłówka przez kompilator Swift, w Swift 4 nie został on wywnioskowany.Przeczytaj więcej na temat propozycji ewolucji Swift na temat tej zmiany
Jak już wspomniano, generalnie
@objc
polega na udostępnieniu pewnych metod środowisku uruchomieniowemu Objective-C, które jest częścią interoperacyjności języka Swift.źródło
@objc
@objc
ujawnia deklaracjęObjective-C runtime
. Rzućmy okiem na#selector
funkcję Swift, aby użyć środowiska uruchomieniowego Objective-C. W takim przypadku możesz zdefiniować Swift@objc private func
[Więcej]Aby użyć funkcji Swift z Objective-C:
NSObject
Marka Swifta:
za. tylko
@objcMembers
klasa - aby ujawnić wszystkiepublic
konstruktory , pola i metody . Dotyczy to również podklasb.
@objc
klasa / wyliczenie / protokół (z wyjątkiem struktury ) [nazwany typ]@objc
class (opcjonalne) - aby ujawnić wartość domyślnąpublic init()
. Lub@objc(<custom_name>)
ustawić własną nazwę dla klasy.@objc
konstruktory , pola i metody - aby je selektywnie ujawnićMetoda Swifta będzie dostępna przy następnym nazewnictwie:
<swiftName>With<firstArgument>:<secondArgument>:
Na przykład:
public func printHelloWorld(arg1: String, arg2:String) //is reached through: [someObject printHelloWorldWithArg1: arg2:];
[
@objc
idynamic
]źródło