Przeszukałem go, ale nie byłem w stanie dowiedzieć się, jaki jest szybki odpowiednik respondsToSelector:
.
Jest to jedyna rzecz, jaką mogłem znaleźć ( szybka alternatywa dla respondsToSelector:), ale nie jest ona zbyt istotna w moim przypadku, ponieważ sprawdza obecność delegata, nie mam delegata, chcę tylko sprawdzić, czy istnieje nowy interfejs API lub nie, gdy działa na urządzeniu, a jeśli nie, powróć do poprzedniej wersji interfejsu API.
objective-c
swift
selector
Gruntcakes
źródło
źródło
NSClassFromString
irespondsToSelector
między innymi mechaniki do sprawdzania nowo zaimplementowanej funkcjonalności, muszę uwierzyć, że mechanizmy te już istnieją lub będą dostępne przed wydaniem. Spróbuj obejrzećAdvanced Interop...
wideo z WWDC.if #available(...)
w Swift 2.x, aby uniknąć używania gorespondsToSelector
w pierwszej kolejności. Ale ty to wiedziałeś. ( Apple.co/1SNGtMQ )Odpowiedzi:
Jak wspomniano, w Swift przez większość czasu możesz osiągnąć to, czego potrzebujesz dzięki
?
opcjonalnemu operatorowi odwijarki . Pozwala to na wywołanie metody na obiekcie wtedy i tylko wtedy, gdy obiekt istnieje (nienil
) i metoda jest zaimplementowana.W przypadku, gdy nadal potrzebujesz
respondsToSelector:
, nadal jest dostępny jako częśćNSObject
protokołu.Jeśli
respondsToSelector:
w Swift wywołujesz typ Obj-C, to działa tak, jak byś się spodziewał. Jeśli używasz go we własnej klasie Swift, musisz upewnić się, że twoja klasa pochodziNSObject
.Oto przykład klasy Swift, którą możesz sprawdzić, czy odpowiada na selektor:
Ważne jest, aby nie pominąć nazw parametrów. W tym przykładzie nie
Selector("sleep::")
jest taki sam jak .Selector("sleep:minutes:")
źródło
let x =
część. Zasadniczoif let x = y
struktura ma rozpakowywać opcjonalne wartości (podobne do!
). Ponieważ otrzymujesz odpowiedźBool
z powrotemrespondsToSelector
, kompilator narzeka, że wynik nie jest typem opcjonalnym (Bool?
).var
zadeklarowanym? Czy nadal reagują w ten sam sposób? W Objective-C mógłbym zrobićif ( [obj respondsToSelector:@selector(setSomeVar:)] ) { ... }
dlasomeVar
własności. Czy działa tak samo, jakvar
s w Swift?Nie ma prawdziwej wymiany Swift.
Możesz to sprawdzić w następujący sposób:
Wywołuje tę metodę
someMethod
tylko wtedy, gdy jest zdefiniowana na obiekcie,someObject
ale można jej używać tylko w przypadku@objc
protokołów, które zadeklarowały metodę jakooptional
.Swift jest z natury bezpiecznym językiem, więc za każdym razem, gdy wywołujesz metodę, Swift musi wiedzieć, że metoda istnieje. Sprawdzanie czasu wykonywania nie jest możliwe. Nie można po prostu wywoływać losowych metod na losowych obiektach.
Nawet w Obj-C powinieneś unikać takich rzeczy, gdy jest to możliwe, ponieważ nie działa to dobrze z ARC (ARC wywołuje wtedy ostrzeżenia
performSelector:
).Jednak podczas sprawdzania dostępnych interfejsów API nadal możesz używać
respondsToSelector:
, nawet jeśli Swift, jeśli masz do czynienia zNSObject
instancjami:źródło
respondsToSelector:
ponieważ zalecenie Apple wyraźnie mówi, że powinieneś to robić. Zobacz tutajrespondsToSelector:
warto go mieć. Ale jeśli przejrzysz odniesienie do Swift, mówią o używaniu podklas dla różnych wersji systemu.if #available(iOS 10) {
A następnie wywołujemy metodę bezpośrednio.Zaktualizuj 20 marca 2017 dla składni Swift 3:
Jeśli nie obchodzi Cię, czy istnieje opcjonalna metoda, po prostu wywołaj
delegate?.optionalMethod?()
W przeciwnym razie użycie
guard
jest prawdopodobnie najlepszym podejściem:Oryginalna odpowiedź:
Możesz użyć metody „jeśli pozwól”, aby przetestować opcjonalny protokół w następujący sposób:
źródło
let theMethod = delegate.userNotificationCenter(_:willPresent:withCompletionHandler:)
Wygląda na to, że musisz zdefiniować swój protokół jako podprotokę NSObjectProtocol ... wtedy otrzymasz metodę ResponsToSelector
zwróć uwagę, że samo podanie @objc nie wystarczyło. Należy również uważać, aby faktyczny delegat był podklasą NSObject - co w Swift może nie być.
źródło
Jeśli metoda, którą testujesz, jest zdefiniowana jako opcjonalna metoda w protokole @objc (która brzmi jak twoja sprawa), użyj opcjonalnego wzoru łączenia jako:
Gdy metoda jest deklarowana jako zwracana
Void
, po prostu użyj:Widzieć:
źródło
if object.method?(args) { ... }
- wywołanie metody, jeśli istnieje, zwróci się,Void
co nie jestnil
object
ma typAnyObject
, możesz przetestować dowolną metodę @objc.Funkcje są pierwszorzędnymi typami w Swift, dzięki czemu można sprawdzić, czy zaimplementowano opcjonalną funkcję zdefiniowaną w protokole, porównując ją do zera:
źródło
Dla swift3
Jeśli chcesz tylko wywołać metodę, uruchom poniższy kod.
self.delegate?.method?()
źródło
W Swift 2 Apple wprowadził nową funkcję o nazwie
API availability checking
, która może być zamiennikiemrespondsToSelector:
metody. Poniższe porównanie fragmentów kodu jest kopiowane z sesji WWDC2015 106 Co nowego w Swift, które moim zdaniem mogą ci pomóc, sprawdź to, jeśli potrzebujesz wiedzieć więcej.źródło
respondsToSelector
podejścia w Swift. Jest tak również dlatego, że sprawdzenie selektora nie było najlepszym rozwiązaniem tego problemu (sprawdzanie dostępności).Dla szybkiego 3.0
źródło
Obecnie (Swift 2.1) możesz to sprawdzić na 3 sposoby:
Używasz „?” odpowiedział @Sulthan
I za pomocą
as?
operatora:Zasadniczo zależy to od tego, co próbujesz osiągnąć:
źródło
Po prostu implementuję to sam w projekcie, patrz kod poniżej. Jak wspomina @Christopher Pickslay, ważne jest, aby pamiętać, że funkcje są pierwszorzędnymi obywatelami i dlatego mogą być traktowane jak zmienne opcjonalne.
źródło
inna możliwa składnia przez swift ..
źródło
Gdy zacząłem aktualizować mój stary projekt do Swift 3.2, po prostu musiałem zmienić metodę z
do:
źródło
Używam
guard let else
, więc mogę zrobić pewne rzeczy domyślne, jeśli delegata func nie jest zaimplementowana.źródło
Swift 3:
protokół
Obiekt
źródło
Odpowiednikiem jest? operator:
importantMethod zostanie wywołany tylko wtedy, gdy myQuestionableObject istnieje i implementuje go.
źródło
?
poimportantMethod