如何在Swift中为UIBarButtonItem设置动作

98

如何在Swift中设置自定义UIBarButtonItem的操作?

以下代码成功地将按钮放置在导航栏中:

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

现在,当按钮被点击时,我想调用func sayHello() { println("Hello") }。到目前为止我的尝试:

现在,当按钮被点击时,我希望调用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() 出现在智能感知中,但不起作用。
谢谢你的帮助。
编辑:为了后人,以下内容可行:
var b = UIBarButtonItem(title: "Continue", style: .Plain, target: self, action:"sayHello")

4
在 Swift 中,您只需将选择器放入字符串中即可传递选择器,例如 action: "sayHello" - Jiaaro
非常感谢。我在压力下需要完成这个任务,之前有些沮丧。 - kmiklas
1
这个问题之前被标记为@selector() in Swift?的重复。然而,这个问题特别询问UIBarButtonItem,而另一个问题则没有。要求初学者将selector的所有用途概括可能对他们来说很困难,因此我取消了重复状态,以便人们可以保持这个问题的最新状态。 - Suragch
6个回答

161
截至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,它将复制包括类型的“限定符号名称”。
var b = UIBarButtonItem(
    title: "Continue",
    style: .Plain,
    target: self,
    action: #selector(sayHello(_:))
)

func sayHello(sender: UIBarButtonItem) {
}

这是因为在Swift 2.3中,调用方法时第一个参数名称不是必需的。
您可以在此处学习有关语法的更多信息:https://swift.org/blog/swift-2-2-new-features/#compile-time-checked-selectors

11
提醒一下,动作函数不能是私有的!我不太确定为什么,但每当我提供某个私有函数的名称时,总是会出现错误。 - maddob
1
如果您正在使用带有冒号的第二个版本,则需要确保函数参数类型与您处理的任何操作相匹配。 - Jason
我原本在使用Selector("sayHello"),现在知道直接使用字符串即可。 - RyanTCB
1
@RyanForsyth 实际上,这个字符串在 Swift 内部被翻译成 Selector("sayHello") - fatuhoku
3
这个答案已经过时。 - dwlz
显示剩余2条评论

44

Swift 4/5 示例

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

@objc func buttonClicked(sender: UIBarButtonItem) {
        
}

6
对于Swift 4来说,你需要在函数声明中添加@objc。在Swift 4之前,这是隐含的。 - Jonathan Cabrera
1
button.target = self - MD.
@Mahesh 不需要设置目标。 - norbDEV
1
@norbDEV 需要为 Swift 5 添加目标。 - Biasi Wiga

6

Swift 5&iOS 13+编程示例

  1. 你必须在函数前加上@objc标记,如下所示的例子!
  2. 在函数名后面不要加括号!只需使用#selector(name)
  3. privatepublic都无所谓;你可以使用私有的。

代码示例

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

如果您不想使用target/action,而是使用#selector,您可以自以来使用primaryAction

// here you can set the title or a image for the UIBarButtonItem
let action = UIAction(title: "", image: UIImage(systemName: "list.dash")) { _ in
    // handler
    print("hello world")
}
        
let barButtonItem = UIBarButtonItem(title: nil,
                                    image: nil,
                                    primaryAction: action,
                                    menu: nil)

0

Swift 5

如果您在Interface Builder中创建了UIBarButtonItem并将outlet连接到item,并希望以编程方式绑定选择器。

不要忘记设置目标和选择器。

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

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

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

现在只需在您想要此barbutton的任何类中继承SuperViewController即可。

感谢阅读。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接