Come impostare l'azione per un UIBarButtonItem in Swift


89

Come può essere impostata l'azione per un UIBarButtonItem personalizzato in Swift?

Il codice seguente inserisce correttamente il pulsante nella barra di navigazione:

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

Ora, vorrei chiamare func sayHello() { println("Hello") }quando viene toccato il pulsante. Finora i miei sforzi:

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

e..

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

e..

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

Nota che sayHello()appare nell'intellisense, ma non funziona.

Grazie per l'aiuto.

EDIT: Per i posteri, le seguenti opere:

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

4
passi selettori in modo rapido semplicemente mettendo il selettore in una stringa,action: "sayHello"
Jiaaro

Grazie mille. Sono sotto pressione per farlo uscire e mi sono sentito frustrato.
kmiklas

1
Questa domanda è stata precedentemente contrassegnata come duplicata di @selector () in Swift? . Tuttavia, questa domanda chiede specificamente UIBarButtonItemmentre l'altra no. Richiedere ai principianti di generalizzare tutti gli usi di selectorpuò essere difficile per loro, quindi rimuovo lo stato duplicato in modo che le persone possano mantenere questa domanda aggiornata.
Suragch

Risposte:


157

A partire da Swift 2.2, esiste una sintassi speciale per i selettori controllati al momento del compilatore. Esso utilizza la sintassi: #selector(methodName).

Swift 3 e versioni successive:

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

func sayHello(sender: UIBarButtonItem) {
}

Se non sei sicuro di come dovrebbe apparire il nome del metodo, esiste una versione speciale del comando copy che è molto utile. Posiziona il cursore da qualche parte nel nome del metodo di base (ad esempio sayHello) e premi Shift+ Control+ Option+ C. Questo inserisce il "Nome simbolo" sulla tastiera da incollare. Se lo tieni premuto Command, copierà anche il "Nome simbolo qualificato" che includerà anche il tipo.

Swift 2.3:

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

func sayHello(sender: UIBarButtonItem) {
}

Questo perché il nome del primo parametro non è richiesto in Swift 2.3 quando si effettua una chiamata al metodo.

Puoi saperne di più sulla sintassi su swift.org qui: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors


11
Solo per menzionare che la funzione di azione non può essere privata ! Non sono proprio sicuro del perché, ma ricevo sempre un errore nel caso in cui
fornissi

Ho capito: "non implementa methodSignatureForSelector"
AlamoPS

1
@AlamoPS Se stai usando la seconda versione con i due punti, dovrai assicurarti che i tipi di parametri della funzione corrispondano a quelli per qualsiasi azione stai gestendo.
Jason

1
@RyanForsyth La stringa viene effettivamente tradotta in Selector("sayHello")dietro le quinte da Swift comunque.
fatuhoku

2
Questa risposta è obsoleta.
Dan Loewenherz

34

Esempio Swift 4/5

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

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}

5
Questo è giusto, per Swift 4 è necessario aggiungere @objcalla dichiarazione di funzione. Fino a Swift 4 questo era implicitamente dedotto.
Jonathan Cabrera

1
button.target = self
Mahesh

@Mahesh non ha bisogno di impostare l'obiettivo
norbDEV

L'obiettivo @norbDEV è necessario per Swift 5
Biasi Wiga,

3

Swift 5 e iOS 13+ Esempio programmatico

  1. È necessario contrassegnare la funzione con @objc , vedere l'esempio di seguito!
  2. Nessuna parentesi dopo il nome della funzione! Basta usare#selector(name) .
  3. privateo publicnon importa; puoi usare privato.

Esempio di codice

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

Possa questo aiutare un po 'di più

Supponiamo che tu voglia creare il pulsante della barra in un file separato (per un approccio modulare) e vuoi restituire il selettore al tuo viewcontroller, puoi fare in questo modo: -

il tuo file di utilità

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];
    }
}

Quindi creare una classe SuperviewController e definire la stessa funzione su di essa.

class SuperViewController: UIViewController {

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

    }
}

e Nella nostra base viewController (che eredita la tua classe SuperviewController) sovrascriverà la stessa funzione

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")    
    } 
}

Ora eredita semplicemente il SuperViewController in qualsiasi classe tu voglia questo barbutton.

Grazie per la lettura


0

Swift 5

se hai creato UIBarButtonItem in Interface Builder e hai collegato la presa all'elemento e desideri associare il selettore a livello di programmazione.

Non dimenticare di impostare target e selettore.

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

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.