Jak ustawić akcję dla UIBarButtonItem w Swift


86

Jak można ustawić akcję dla niestandardowego elementu UIBarButtonItem w języku Swift?

Poniższy kod pomyślnie umieszcza przycisk na pasku nawigacyjnym:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:nil)
self.navigationItem.rightBarButtonItem = b

Teraz chciałbym zadzwonić func sayHello() { println("Hello") }po dotknięciu przycisku. Moje dotychczasowe wysiłki:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:sayHello:)
// also with `sayHello` `sayHello()`, and `sayHello():`

i..

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:@selector(sayHello:))
// also with `sayHello` `sayHello()`, and `sayHello():`

i..

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:@selector(self.sayHello:))
// also with `self.sayHello` `self.sayHello()`, and `self.sayHello():`

Zauważ, że sayHello()pojawia się w trybie Intellisense, ale nie działa.

Dzięki za pomoc.

EDYCJA: Dla potomnych następujące prace:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")

4
szybko mijasz selektory, po prostu umieszczając selektor w ciągu,action: "sayHello"
— Jiaaro

Dziękuję bardzo. Jestem pod presją, żeby to z siebie wyrzucić i zaczynałem się frustrować.
— kmiklas

1
To pytanie było wcześniej oznaczone jako duplikat @selector () w Swift? . Jednak to pytanie dotyczy konkretnie, UIBarButtonItempodczas gdy drugie nie. Wymaganie od początkujących uogólniania wszystkich zastosowań selectormoże być dla nich trudne, więc usuwam status zduplikowany, aby ludzie mogli aktualizować to pytanie.
— Suragch

Odpowiedzi:


157

Od wersji Swift 2.2 istnieje specjalna składnia dla selektorów sprawdzanych w czasie kompilacji. Używa składni: #selector(methodName).

Swift 3 i nowsze:

var b = UIBarButtonItem(
    title: "Continue",
    style: .plain,
    target: self,
    action: #selector(sayHello(sender:))
)

func sayHello(sender: UIBarButtonItem) {
}

Jeśli nie jesteś pewien, jak powinna wyglądać nazwa metody, istnieje specjalna wersja polecenia kopiowania, która jest bardzo pomocna. Umieść kursor gdzieś w nazwie metody bazowej (np. SayHello) i naciśnij Shift+ Control+ Option+ C. To powoduje umieszczenie „nazwy symbolu” na klawiaturze do wklejenia. Jeśli również Commandgo posiadasz , skopiuje „kwalifikowaną nazwę symbolu”, która będzie zawierała również typ.

Swift 2.3:

var b = UIBarButtonItem(
    title: "Continue",
    style: .Plain,
    target: self,
    action: #selector(sayHello(_:))
)

func sayHello(sender: UIBarButtonItem) {
}

Dzieje się tak, ponieważ pierwsza nazwa parametru nie jest wymagana w Swift 2.3 podczas wywoływania metody.

Możesz dowiedzieć się więcej o składni na swift.org tutaj: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors


11
Wystarczy wspomnieć, że funkcja akcji nie może być prywatna ! Nie bardzo wiem dlaczego, ale zawsze
— pojawia

Mam to: „nie implementuje metody methodSignatureForSelector”
— AlamoPS,

1
@AlamoPS Jeśli używasz drugiej wersji z dwukropkiem, musisz się upewnić, że typy parametrów funkcji pasują do tego dla każdej wykonywanej czynności.
— Jason

1
@RyanForsyth Ciąg i tak jest tłumaczony Selector("sayHello")za kulisami przez Swift.
— fatuhoku

2
Ta odpowiedź jest nieaktualna.
— Dan Loewenherz

33

Przykład Swift 4/5

button.target = self
button.action = #selector(buttonClicked(sender:))

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}

5
To prawda, dla Swift 4 musisz dodać @objcdo deklaracji funkcji. Aż do wersji Swift 4 wywnioskowano to niejawnie.
— Jonathan Cabrera

1
button.target = self
— Mahesh

@Mahesh nie musi ustawiać celu
— norbDEV

Cel @norbDEV jest potrzebny dla Swift 5
— Biasi Wiga

2

Przykład automatyzacji Swift 5 i iOS 13+

  1. Musisz oznaczyć swoją funkcję @objc, patrz poniższy przykład!
  2. Po nazwie funkcji nie ma nawiasów! Po prostu użyj #selector(name).
  3. privatelub publicnie ma znaczenia; możesz użyć prywatnego.

Przykład kodu

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    
    let menuButtonImage = UIImage(systemName: "flame")
    let menuButton = UIBarButtonItem(image: menuButtonImage, style: .plain, target: self, action: #selector(didTapMenuButton))
    navigationItem.rightBarButtonItem = menuButton
}

@objc public func didTapMenuButton() {
    print("Hello World")
}

0

Niech ten pomoże trochę więcej

Załóżmy, że jeśli chcesz utworzyć przycisk paska w oddzielnym pliku (dla podejścia modułowego) i chcesz zwrócić selektor z powrotem do kontrolera widoku, możesz zrobić to w następujący sposób: -

plik narzędziowy

class GeneralUtility {

    class func customeNavigationBar(viewController: UIViewController,title:String){
        let add = UIBarButtonItem(title: "Play", style: .plain, target: viewController, action: #selector(SuperViewController.buttonClicked(sender:)));  
      viewController.navigationController?.navigationBar.topItem?.rightBarButtonItems = [add];
    }
}

Następnie utwórz klasę SuperviewController i zdefiniuj w niej tę samą funkcję.

class SuperViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
            // Do any additional setup after loading the view.
    }
    @objc func buttonClicked(sender: UIBarButtonItem) {

    }
}

iw naszym podstawowym viewController (który dziedziczy twoją klasę SuperviewController) przesłania tę samą funkcję

import UIKit

class HomeViewController: SuperViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    override func viewWillAppear(_ animated: Bool) {
        GeneralUtility.customeNavigationBar(viewController: self,title:"Event");
    }

    @objc override func buttonClicked(sender: UIBarButtonItem) {
      print("button clicked")    
    } 
}

Teraz po prostu odziedzicz SuperViewController w dowolnej klasie, w której chcesz ten barbutton.

Dzięki za przeczytanie


0

Szybki 5

jeśli utworzyłeś UIBarButtonItemw Interface Builder i podłączyłeś outlet do elementu i chcesz programowo powiązać selektor.

Nie zapomnij ustawić celu i selektora.

addAppointmentButton.action = #selector(moveToAddAppointment)
addAppointmentButton.target = self

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.