2016-04-14 19 views
6

Tworzę widok programowo, a dodając funkcję więc działanie jest odpowiedzią na wydarzenia UIControlEvents.TouchUpInside:właściwy sposób korzystać z selektorów w Swift

button.addTarget(self, action: action, forControlEvents: 
UIControlEvents.TouchUpInside) 

So, przechodząc do dokumentacji mam dodaje się tę czynność jako selektor:

#selector(ViewController.onRegularClick) 

XCode następnie skarg:

argument #selector oznacza Met hod że nie jest narażony na Objective-C

Więc muszę skonfigurować funkcję obsługi z:

@objc func onRegularClick(sender: UIButton) 

Czy ktoś proszę umieścić ten Noob na właściwym kierunku, prowadząc mnie do Dokumentacja, a nawet podać krótkie wyjaśnienie, na:

  1. dlaczego nie mogę już przekazać po prostu nazwę funkcji String do działania?
  2. jaki jest właściwy sposób wdrożenia tego po Swift Way? Korzystasz z klasy Selector?
  3. dlaczego musimy przekazać słowo kluczowe @objc i jak wpływa ono na funkcję?

Dziękujemy!

+0

Można sprawdzić szczegóły w [Nowe funkcje w Swift 2.2] (https: // Swift .org/blog/swift-2-2-nowe-funkcje # kompilowane-sprawdzane-selektory) – Inhan

+0

Dziękuję, naprawdę fajny artykuł! – josetapadas

Odpowiedz

7
  1. dlaczego nie mogę już przekazywać po prostu nazwy funkcji String do akcji?

Korzystanie Struny do selektorów jest przestarzała i należy teraz napisać #selector(methodName) zamiast "methodName". Jeśli metoda methodName() nie istnieje, otrzymasz błąd kompilacji - kolejna klasa błędów zostanie wyeliminowana podczas kompilacji. Nie było to możliwe przy strunach.

  1. jaki jest właściwy sposób wdrożenia tego po Swift Way? Korzystasz z klasy Selector?

Zrobiłeś to we właściwy sposób:

button.addTarget(self, action: #selector(ClassName.methodName(_:)), forControlEvents: UIControlEvents.TouchUpInside)

  1. Dlaczego musimy zdać @objc słowa kluczowego i jak to wpływa na funkcjonować?

w Swift normalne podejście do związania połączenia metody i organami metoda w czasie kompilacji (jak C i C++ nie). Cel C robi to w czasie wykonywania. Tak więc w Objective C możesz robić rzeczy, które nie są możliwe w Swift - na przykład możliwa jest wymiana implementacji metody w czasie wykonywania (nazywa się to metodą swizzling). Cocoa został zaprojektowany do pracy z podejściem Objective C i dlatego musisz poinformować kompilator, że twoja metoda Swift powinna zostać skompilowana w stylu podobnym do ObjectiveC. Jeśli twoja klasa odziedziczy NSObject, zostanie skompilowany w stylu podobnym do ObjC, nawet bez słowa kluczowego @objc.

7
  1. No, to się nazywa ewolucja
  2. Gdy istnieją pewne argumenty metody, należy zadeklarować selektor jak:

    let selector = #selector(YourClass.selector(_:)) 
    

    Można wpisać tylko #selector(selector(_:)) jeśli przełącznik jest w pozycji ta sama klasa dzwoniącego. _: oznacza, że ​​akceptuje jeden parametr. Tak więc, jeśli akceptują więcej parametrów, powinieneś zrobić coś takiego: (_:, _:) i tak dalej.

  3. I okazało się, że potrzebna jest tylko @objc gdy funkcja jest zadeklarowana jako prywatne lub obiekt nie dziedziczy z NSObject

+0

Odważę się, że '@ objc' jest również potrzebny, jeśli twoja klasa nie jest w hierarchii' NSObject'? Co prawda będzie to rzadkość, ponieważ najprawdopodobniej otrzymasz informację zwrotną od interfejsu użytkownika i dlatego jesteś potomkiem "UIViewController". – Tommy

+0

Dodałem go do odpowiedzi, dziękuję –

+0

Nie wiedziałem, że prywatne funkcje mogą być selektorami z atrybutem objc! Wielkie dzięki! +1 – Darko

2

1: Obecnie można, ale stworzy przestarzałej ostrzeżenie . W Swift 3 będzie to błąd, więc powinieneś to naprawić wkrótce. Jest to robione , ponieważ właśnie przy użyciu ciągu nie można sprawdzić przez kompilator, jeśli funkcja rzeczywiście istnieje i jest to poprawna funkcja Celu C , która może być rozwiązana dynamicznie podczas wykonywania.

2: Zrób to w ten sposób:

button.addTarget(self, action: #selector(MyViewControllerClass.buttonPressed(_:)), forControlEvents: UIControlEvents.TouchUpInside) 

3: Zwykle nie trzeba użyć atrybutu @objc. Zakładam, że Twoja klasa ViewController jest (z jakiegokolwiek powodu) nie pochodzi z UIViewController. Jeśli wywodzi się z UIViewController, dziedziczy również wymagane zachowanie ObjC do wywoływania selektorów w funkcjach.

1

Dla swift3.0 prostu zrobić jak poniżej kodu:

 yourButton.addTarget(self, action: #selector(yourButtonPressed), for: .touchUpInside) 

i yourButtonPressed metoda

@IBAction func yourButtonPressed(sender:UIButton) { 
    // Do your code here 
}