Як встановити дію для елемента 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, але не працює.

Спасибі за вашу допомогу.

EDIT: Для нащадків наступні роботи:

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

4
ви швидко пропускаєте селектори, просто action: "sayHello"
вставивши

Дуже дякую. Я відчуваю тиск, щоб це вивести, і я був розчарований.
kmiklas

1
Це питання раніше було позначено як дублікат @selector () у Swift? . Однак це питання конкретно задає питання, UIBarButtonItemтоді як інше - ні. Вимагати від початківців узагальнення всіх видів використання selectorдля них може бути важко, тому я видаляю статус дублікатів, щоб люди могли постійно оновлювати це питання.
Сурагч

Відповіді:


157

Станом на Swift 2.2 існує спеціальний синтаксис для селекторів, перевірених під час компіляції. Він використовує синтаксис: #selector(methodName).

Свіфт 3 і пізніші версії:

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

func sayHello(sender: UIBarButtonItem) {
}

Якщо ви не впевнені, як має виглядати назва методу, існує спеціальна версія команди copy, яка дуже корисна. Помістіть курсор десь в назву базового методу (наприклад, sayHello) і натисніть Shift+ Control+ Option+ C. Таким чином на клавіатурі буде вставлено «Ім'я символу». Якщо ви також утримуєте, Commandвін скопіює "Ім'я кваліфікованого символу", яке також включатиме тип.

Свіфт 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-cked-selectors


11
Зазначимо лише, що функція дії не може бути приватною ! Я не зовсім впевнений, чому, але я завжди отримую помилку на випадок, якщо я
вказав

Я отримав таке: "не реалізує methodSignatureForSelector"
AlamoPS

1
@AlamoPS Якщо ви використовуєте 2-ю версію з двокрапкою, вам потрібно переконатися, що типи параметрів функції збігаються з тими, які дії ви обробляєте.
Джейсон,

1
@RyanForsyth Струк фактично перекладається Свіфтом у кулуари Selector("sayHello").
Фатухоку

2
Ця відповідь застаріла.
Dan Loewenherz

33

Приклад Swift 4/5

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

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}

5
Це правильно, для Swift 4 вам потрібно додати @objcдо декларації функції. До Swift 4 це було неявно виведено.
Джонатан Кабрера,

1
button.target = self
Махеш

@Mahesh не потрібно встановлювати ціль
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

Стрімкий 5

якщо ви створили UIBarButtonItemв Interface Builder і підключили розетку до елемента і хочете прив'язати селектор програмно.

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

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

@objc private func moveToAddAppointment() {
     self.presenter.goToCreateNewAppointment()
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.