Как установить действие для UIBarButtonItem в Swift

86

Как можно настроить действие для настраиваемого UIBarButtonItem в Swift?

Следующий код успешно помещает кнопку на панель навигации:

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

Теперь я хотел бы позвонить, func sayHello() { println("Hello") }когда нажата кнопка. Мои усилия на данный момент:

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

а также..

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

а также..

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

Обратите внимание, что sayHello()появляется в intellisense, но не работает.

Спасибо за вашу помощь.

РЕДАКТИРОВАТЬ: Для потомков работает следующее:

var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")
kmiklas
источник
4
Вы быстро передаете селекторы, просто помещая селектор в строку,action: "sayHello"
Jiaaro 08
Огромное спасибо. Я нахожусь под давлением, чтобы вытащить это, и меня это расстраивало.
kmiklas 08
1
Этот вопрос ранее был отмечен как дубликат @selector () в Swift? . Однако в этом вопросе конкретно задается вопрос, UIBarButtonItemа в другом - нет. Требовать от новичков обобщения всех вариантов использования selectorможет быть для них трудным, поэтому я удаляю повторяющийся статус, чтобы люди могли обновлять этот вопрос.
Suragch

Ответы:

157

Начиная с Swift 2.2, существует специальный синтаксис для селекторов, проверяемых во время компиляции. Он использует синтаксис: #selector(methodName).

Swift 3 и новее:

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

func sayHello(sender: UIBarButtonItem) {
}

Если вы не уверены, как должно выглядеть имя метода, существует специальная версия команды копирования, которая очень полезна. Поместите курсор где-нибудь в имя базового метода (например, sayHello) и нажмите Shift+ Control+ Option+ C. Это помещает «Имя символа» на клавиатуру для вставки. Если вы также будете удерживать, Commandон скопирует «Полное имя символа», которое также будет включать тип.

Swift 2.3:

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

func sayHello(sender: UIBarButtonItem) {
}

Это потому, что первое имя параметра не требуется в Swift 2.3 при вызове метода.

Вы можете узнать больше о синтаксисе на swift.org здесь: https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors

Дрюаг
источник
11
Просто упомяну, что функция действия не может быть частной ! Я не совсем уверен, почему, но я всегда получаю сообщение об ошибке, если
указываю
Я получил следующее: «не реализует methodSignatureForSelector»
AlamoPS
1
@AlamoPS Если вы используете вторую версию с двоеточием, вам нужно убедиться, что типы параметров функции соответствуют этому для любого действия, которое вы обрабатываете.
Джейсон
1
@RyanForsyth Строка фактически переводится Selector("sayHello")Swift за кулисы.
fatuhoku
2
Этот ответ устарел.
Dan Loewenherz
33

Пример Swift 4/5

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

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}
norbDEV
источник
5
Это правильно, для Swift 4 нужно добавить @objcв объявление функции. Вплоть до Swift 4 это предполагалось неявно.
Джонатан Кабрера
1
button.target = self
Махеш
@Mahesh не нужно устанавливать цель
norbDEV
Цель @norbDEV необходима для Swift 5
Biasi Wiga
2

Пример алгоритмической продажи Swift 5 и iOS 13+

  1. Вы должны отметить свою функцию значком @objc, см. Пример ниже!
  2. После имени функции скобки не ставятся! Просто используйте #selector(name).
  3. privateили publicне имеет значения; вы можете использовать приват.

Пример кода

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

Пусть это поможет еще немного

Предположим, что если вы хотите сделать кнопку панели в отдельном файле (для модульного подхода) и хотите вернуть селектор обратно своему контроллеру представления, вы можете сделать следующее: -

ваш служебный файл

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

Затем создайте класс SuperviewController и определите в нем ту же функцию.

class SuperViewController: UIViewController {

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

    }
}

и в нашем базовом viewController (который наследует ваш класс SuperviewController) переопределить ту же функцию

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

Теперь просто унаследуйте SuperViewController от того класса, который вам нужен.

Спасибо за прочитанное

Анураг Бхакуни
источник
0

Swift 5

если вы создали UIBarButtonItemв Интерфейсном Разработчике и подключили розетку к элементу и хотите привязать селектор программно.

Не забудьте установить цель и селектор.

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

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
Махеш
источник