Cómo configurar la acción para un UIBarButtonItem en Swift

86

¿Cómo se puede configurar la acción para un UIBarButtonItem personalizado en Swift?

El siguiente código coloca correctamente el botón en la barra de navegación:

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

Ahora, me gustaría llamar func sayHello() { println("Hello") }cuando se toque el botón. Mis esfuerzos hasta ahora:

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

y..

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

y..

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

Tenga sayHello()en cuenta que aparece en el intellisense, pero no funciona.

Gracias por tu ayuda.

EDITAR: Para la posteridad, las siguientes obras:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")
kmiklas
fuente
4
pasa selectores rápidamente con solo poner el selector en una cadena,action: "sayHello"
Jiaaro
Muchas gracias. Estoy bajo presión para sacar esto y me estaba frustrando.
kmiklas
1
Esta pregunta se marcó previamente como un duplicado de @selector () en Swift? . Sin embargo, esta pregunta pregunta específicamente sobre UIBarButtonItemmientras que la otra no. Requerir que los principiantes generalicen todos los usos de selectorpuede ser difícil para ellos, por lo que eliminaré el estado duplicado para que la gente pueda mantener esta pregunta actualizada.
Suragch

Respuestas:

157

A partir de Swift 2.2, existe una sintaxis especial para los selectores comprobados en tiempo de compilación. Utiliza la sintaxis: #selector(methodName).

Swift 3 y posteriores:

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

func sayHello(sender: UIBarButtonItem) {
}

Si no está seguro de cómo debería verse el nombre del método, existe una versión especial del comando de copia que es muy útil. Coloque el cursor en algún lugar del nombre del método base (por ejemplo, sayHello) y presione Shift+ Control+ Option+ C. Eso coloca el 'Nombre del símbolo' en su teclado para pegarlo. Si también lo mantiene presionado Command, se copiará el 'Nombre de símbolo calificado' que incluirá el tipo también.

Swift 2.3:

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

func sayHello(sender: UIBarButtonItem) {
}

Esto se debe a que el primer nombre de parámetro no es necesario en Swift 2.3 al realizar una llamada a un método.

Puede obtener más información sobre la sintaxis en swift.org aquí: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors

dibujar
fuente
11
¡Solo para mencionar que la función de acción no puede ser privada ! No estoy realmente seguro de por qué, pero siempre obtengo un error en caso de que proporcione el nombre de alguna función privada
maddob
Recibí esto: "no implementa methodSignatureForSelector"
AlamoPS
1
@AlamoPS Si está utilizando la segunda versión con dos puntos, deberá asegurarse de que los tipos de parámetros de la función coincidan con la de cualquier acción que esté manejando.
Jason
1
@RyanForsyth De Selector("sayHello")todos modos, Swift traduce la cadena en detrás de escena.
fatuhoku
2
Esta respuesta está desactualizada.
Dan Loewenherz
33

Ejemplo de Swift 4/5

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

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}
norbDEV
fuente
5
Esto es correcto, para Swift 4 debe agregar @objca la declaración de función. Hasta Swift 4, esto se infirió implícitamente.
Jonathan Cabrera
1
button.target = self
Mahesh
@Mahesh no necesita establecer el objetivo
norbDEV
El objetivo de @norbDEV es necesario para Swift 5
Biasi Wiga
2

Ejemplo programático de Swift 5 y iOS 13+

  1. Debe marcar su función con @objc, ¡vea el ejemplo a continuación!
  2. ¡Sin paréntesis después del nombre de la función! Solo usa #selector(name).
  3. privateo publicno importa; puede usar privado.

Ejemplo de código

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
fuente
0

Que este ayude un poco más

Supongamos que si desea hacer el botón de la barra en un archivo separado (para un enfoque modular) y desea devolver el selector a su controlador de vista, puede hacer lo siguiente: -

su archivo de utilidad

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

Luego, cree una clase SuperviewController y defina la misma función en ella.

class SuperViewController: UIViewController {

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

    }
}

y en nuestro viewController base (que hereda su clase SuperviewController) anula la misma función

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

Ahora simplemente herede el SuperViewController en la clase que desee este botón de barra.

Gracias por la lectura

Anurag Bhakuni
fuente
0

Rápido 5

si ha creado UIBarButtonItemen Interface Builder y ha conectado la salida al artículo y desea vincular el selector mediante programación.

No olvide configurar el objetivo y el selector.

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

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