So legen Sie die Aktion für ein UIBarButtonItem in Swift fest

84

Wie kann die Aktion für ein benutzerdefiniertes UIBarButtonItem in Swift festgelegt werden?

Der folgende Code platziert die Schaltfläche erfolgreich in der Navigationsleiste:

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

Jetzt möchte ich anrufen, func sayHello() { println("Hello") }wenn die Taste berührt wird. Meine bisherigen Bemühungen:

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

und..

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

und..

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

Beachten Sie, dass dies sayHello()im Intellisense angezeigt wird, aber nicht funktioniert.

Danke für Ihre Hilfe.

EDIT: Für die Nachwelt funktionieren folgende Werke:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")
kmiklas
quelle
4
Sie übergeben Selektoren schnell, indem Sie einfach den Selektor in eine Zeichenfolge setzen,action: "sayHello"
Jiaaro
Ich danke dir sehr. Ich stehe unter dem Druck, dies herauszubekommen, und war frustriert.
kmiklas
1
Diese Frage wurde zuvor in Swift als Duplikat von @selector () markiert . . Diese Frage stellt jedoch speziell die Frage, UIBarButtonItemwährend die andere dies nicht tut. Es selectorkann für sie schwierig sein, Anfänger zu verpflichten, alle Verwendungen von zu verallgemeinern. Daher entferne ich den doppelten Status, damit die Leute diese Frage auf dem neuesten Stand halten können.
Suragch

Antworten:

155

Ab Swift 2.2 gibt es eine spezielle Syntax für Selektoren, die zur Compilerzeit überprüft wurden. Es verwendet die Syntax : #selector(methodName).

Swift 3 und höher:

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

func sayHello(sender: UIBarButtonItem) {
}

Wenn Sie sich nicht sicher sind, wie der Methodenname aussehen soll, gibt es eine spezielle Version des Kopierbefehls, die sehr hilfreich ist. Setzen Sie den Cursor irgendwo in der Basismethodennamen (zB sayHello) und drücken Sie Shift+ Control+ Option+ C. Dadurch wird der Symbolname auf Ihrer Tastatur eingefügt. Wenn Sie auch gedrückt halten Command, wird der 'Name des qualifizierten Symbols' kopiert, der auch den Typ enthält.

Swift 2.3:

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

func sayHello(sender: UIBarButtonItem) {
}

Dies liegt daran, dass der erste Parametername in Swift 2.3 beim Ausführen eines Methodenaufrufs nicht erforderlich ist.

Weitere Informationen zur Syntax auf swift.org finden Sie hier: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors

Drawag
quelle
10
Nur um zu erwähnen, dass die Aktionsfunktion nicht privat sein kann ! Ich bin mir nicht sicher warum, aber ich bekomme immer eine Fehlermeldung, wenn ich den Namen einer privaten Funktion angegeben habe
Maddob
Ich habe folgendes: "implementiert methodSignatureForSelector nicht"
AlamoPS
1
@AlamoPS Wenn Sie die 2. Version mit dem Doppelpunkt verwenden, müssen Sie sicherstellen, dass die Funktionsparametertypen für jede Aktion, die Sie ausführen, mit dieser übereinstimmen.
Jason
1
@ RyanForsyth Der String wird Selector("sayHello")ohnehin von Swift hinter die Kulissen übersetzt .
Fatuhoku
1
Diese Antwort ist veraltet.
Dan Loewenherz
31

Schnelles 4/5-Beispiel

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

@objc func buttonClicked(sender: UIBarButtonItem) {

}
norbDEV
quelle
5
Dies ist richtig, für Swift 4 müssen Sie @objcder Funktionsdeklaration hinzufügen . Bis Swift 4 wurde dies implizit abgeleitet.
Jonathan Cabrera
button.target = self
Mahesh
@ Mahesh muss das Ziel nicht festlegen
norbDEV
0

Möge dieser etwas mehr helfen

Angenommen, Sie möchten die Balkenschaltfläche in einer separaten Datei erstellen (für einen modularen Ansatz) und Ihrem Ansichtscontroller den Selektor zurückgeben. Gehen Sie dazu folgendermaßen vor:

Ihre Utility-Datei

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

Erstellen Sie dann eine SuperviewController-Klasse und definieren Sie dieselbe Funktion darauf.

class SuperViewController: UIViewController {

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

    }
}

und In unserem Basis-ViewController (der Ihre SuperviewController-Klasse erbt) wird dieselbe Funktion überschrieben

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

Erben Sie jetzt einfach den SuperViewController in der Klasse, in der Sie diesen Barbutton haben möchten.

Danke für das Lesen

Anurag Bhakuni
quelle
0

Swift 5

Wenn Sie UIBarButtonItemin Interface Builder erstellt haben und die Steckdose mit dem Element verbunden haben und den Selektor programmgesteuert binden möchten.

Vergessen Sie nicht, Ziel und Auswahl festzulegen.

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

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
Mahesh
quelle
0

Swift 5 & iOS 13+ Programmatisches Beispiel

  1. Sie müssen Ihre Funktion mit markieren @objc, siehe Beispiel unten!
  2. Nach dem Funktionsnamen folgt keine Klammer! Einfach benutzen #selector(name).
  3. privateoder publicspielt keine Rolle; Sie können privat verwenden.

Codebeispiel

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