2016-03-22 10 views
36

Przełączam składnię mojego projektu w kierunku Swift 2.2 (który xCode pomaga mi automatycznie); jednak nie rozumiem nowej składni #selector().Zrozumienie składni selektora języka Swift 2.2 - #selector()

Jako przykład:

timer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, 
      selector: #selector(MyVC.timerCalled(_:)), //new selector syntax! 
      userInfo: nil, repeats: true) 

ten selektor #selector(MyVC.timerCalled(_:))

Czego _: oznaczać? Czy możesz dodać inne zmienne do tego selektora? Powiedz, #MyVC.timerCalled(_:whateverVar).

Ogólne informacje na temat tego, co różni się w tej składni w przeciwieństwie do implementacji opartej na ciągach z wcześniejszych wersji Swiftu są bardzo doceniane.

+2

Myślę, że dobrze to wyjaśnię tutaj: http://stackoverflow.com/questions/35658334/how-do-i-resolve-ambiguous-use-of-compile-error-with-swift-selector-syntax/35658335# 35658335 – matt

+0

@ matt's Odpowiedź dokładniej odnosi się do składni, w tym do użytecznej dyskusji na temat radzenia sobie z przeciążonymi metodami. – Stuart

Odpowiedz

31

Bit w nawiasie jest mechanizmem identyfikacji listę argumentów dla selektora, który chcesz.

Polecam spojrzeć na propozycję Generalized Naming od Swift Evolution. Obejmuje przypadki, w których masz wiele funkcji, które różnią się jedynie etykietami parametrów i trzeba się do nich odnieść. Przykład z tego dokumentu brzmi:

extension UIView { 
    func insertSubview(view: UIView, at index: Int) 
    func insertSubview(view: UIView, aboveSubview siblingSubview: UIView) 
    func insertSubview(view: UIView, belowSubview siblingSubview: UIView) 
} 

Jeśli chciał uzyskać wartość funkcji dla jednego z tych, których wynik jest niejednoznaczny:

let fn = someView.insertSubview // ambiguous: could be any of the three methods 

Rozwiązanie wdrożone jest dodanie etykiet argumentów, bez wpisać informację do kodu, który generuje wartość funkcji do dwuznaczności, które chcesz:

let fn = someView.insertSubview(_:at:) 
let fn1 = someView.insertSubview(_:aboveSubview:) 

Zobacz jak etykiety są dodawane w parens?

Propozycja ta odegrała rolę w jednym, które najbardziej bezpośrednio dotyczy zapytanie:

Referencing the Objective-C selector of a method

W tym konkretnym przypadku selektor chcesz zapoznać się jest timerCalled: która jest funkcją jednego parametru nie ma etykiety. Stąd (_:). Znak podkreślenia oznacza, że ​​etykieta nie jest określona, ​​a dwukropek.

8

W ten sposób sygnatury metody Swift są reprezentowane w dokumentacji i zaczynają być używane w nowych funkcjach językowych, takich jak składnia #selector() do wyrażania metod za pomocą ich list argumentów.

Każdy dwukropek (:) reprezentuje parametr metody. Dla nazwanych parametrów dwukropek jest poprzedzony zewnętrzną nazwą parametru; w przypadku parametrów bez nazwy używane jest podkreślenie (_).

Tak na przykład, MyVC.timerCalled(_:)) wskazuje sposób na rodzaj MyVC z jednym nienazwanym parametrem, który może zostać uznana za słuszne:

func timerCalled(timer: NSTimer) { ... } 

(Zauważ, że timer jest nazwa parametru wewnętrzny, ponieważ domyślnie pierwszy parametr metody jest nienazwany)

Typ (MyVC w twoim przykładzie) można również pominąć, jeśli znajduje się w tym samym zakresie deklaracji #selector().

Bardziej złożony przykład mógłby wyglądać następująco:

let sel = #selector(aMethodWithSeveralParameters(_:secondParam:thirdParam:)) 

... 

func aMethodWithSeveralParameters(firstParam: Int, secondParam: Int, thirdParam: Int) { ... } 
19

Swift 2.2 ma przestarzałe selektory Stringified: w swift 2.0, używamy do zapisu selektora jako String, np. "buttonClicked". Wadą tego podejścia jest to, że kompilator nie może sprawdzić, czy metoda rzeczywiście istnieje, czy nie w czasie kompilacji (nawet, jeśli została błędnie napisana).

EX: 1

func buttonClicked(){ 
} 

więc powyższa metoda w nowym podejściu można nazwać jako #selector(buttonClicked)

EX: 2

func buttonClicked(stringValue : String){ 
} 

więc powyższa metoda w nowe podejście można nazwać jako #selector(buttonClicked(_:))

EX: 3

func buttonClicked(stringValue : String, indexValue : Int){ 
} 

więc powyższa metoda z parametrów nowego podejścia można nazwać jako #selector(buttonClicked(_:indexValue:))

+0

Hej, właśnie czytałem to pytanie. Czy mógłbyś krótko wyjaśnić mi, dlaczego kompilator naprawił/zmienił powyższy przykład na #selector (YourClass.buttonClicked) zamiast tylko #selector (buttonClicked) podczas konwersji do Swift 2.2. Czy jest różnica między 2? Dziękuję – crashoverride777

+0

@ crashoverride777 Myślę, że twoje pytanie zostało wyjaśnione tutaj wyraźnie .. http://stackoverflow.com/questions/24007650/selector-in-swift?rq=1 –

+0

Myślę, że zawsze trzeba przedrostek deklaracji metody z @objc – blackjacx

9

Rozważmy poniższy kod na dodanie przycisku w celu szybkiej 3 używająC#selector

button.addTarget(self, action: #selector(self.buttonAction(sender:)), 
         for: UIControlEvents.touchUpInside) 

func buttonAction(sender:UIButton!){ 

} 

Ta składnia pracował dla mnie podczas migracji do szybkiej 3

+0

Pytanie dotyczy WERSJI 2 ... – FonzTech

Powiązane problemy