在 Swift 中将参数附加到 button.addTarget 操作

我试图传递一个额外的参数到 buttonClick 动作,但是不能工作出什么语法应该在 Swift。

button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)

返回文章页面任何我的按钮译者:

func buttonClicked(sender:UIButton)
{
println("hello")
}

有人知道吗?

谢谢你的帮助。

162349 次浏览

您不能在 addTarget:.1中传递自定义参数。一种替代方法是设置按钮的 tag属性,并根据标记执行工作。

button.tag = 5
button.addTarget(self, action: "buttonClicked:",
forControlEvents: UIControlEvents.TouchUpInside)

或者对于 Swift 2.2或者更高:

button.tag = 5
button.addTarget(self,action:#selector(buttonClicked),
forControlEvents:.TouchUpInside)

现在执行基于 tag属性的逻辑

@objc func buttonClicked(sender:UIButton)
{
if(sender.tag == 5){


var abc = "argOne" //Do something for tag 5
}
print("hello")
}

如果希望向 buttonClicks 方法发送其他参数(例如 indexPath 或 urlString) ,可以对 UIButton 进行子类化:

class SubclassedUIButton: UIButton {
var indexPath: Int?
var urlString: String?
}

确保将标识检查器中的按钮类更改为子类 UIButton。您可以使用 sender.indexPathsender.urlString访问 buttonClick 方法中的参数。

注意: 如果按钮位于单元格内,可以在 cellForRowAtIndexPath 方法(创建按钮的位置)中设置这些附加参数的值。

适用于 Swift 2.X 及以上版本

button.addTarget(self,action:#selector(YourControllerName.buttonClicked(_:)),
forControlEvents:.TouchUpInside)

For Swift 3.0 you can use following

button.addTarget(self, action: #selector(YourViewController.YourMethodName(_:)), for:.touchUpInside)


func YourMethodName(_ sender : UIButton) {
print(sender.tag)


}

Swift 3.0代码

self.timer = Timer.scheduledTimer(timeInterval: timeInterval, target: self, selector:#selector(fetchAutocompletePlaces(timer:)), userInfo:[textView.text], repeats: true)


func fetchAutocompletePlaces(timer : Timer) {


let keyword = timer.userInfo
}

You can send value in 'userinfo' and use that as parameter in the function.

If you have a loop of buttons like me you can try something like this

var buttonTags:[Int:String]? // can be [Int:Any]
let myArray = [0:"a",1:"b"]
for (index,value) in myArray {


let button = // Create a button


buttonTags?[index] = myArray[index]
button.tag = index
button.addTarget(self, action: #selector(buttonAction(_:)), for: .touchDown)


}
@objc func buttonAction(_ sender:UIButton) {


let myString = buttonTags[sender.tag]


}

Swift 4.0代码(又来了)

被调用的操作应该像这样标记,因为这是快速函数的语法,用于将函数导出到目标 c 语言中。

@objc func deleteAction(sender: UIButton) {
}

创建一些工作按钮:

let deleteButton = UIButton(type: .roundedRect)
deleteButton.setTitle("Delete", for: [])
deleteButton.addTarget(self, action: #selector(
MyController.deleteAction(sender:)), for: .touchUpInside)

我很感激每个人都说要使用标记,但是实际上您需要扩展 UIButton 类并在那里简单地添加对象。.

像这样扩展 UIButton (在 Swift 4中)

import UIKit
class PassableUIButton: UIButton{
var params: Dictionary<String, Any>
override init(frame: CGRect) {
self.params = [:]
super.init(frame: frame)
}


required init?(coder aDecoder: NSCoder) {
self.params = [:]
super.init(coder: aDecoder)
}
}

那么您的呼叫可能被调用(请注意 Selector(("webButtonTouched:"))中的冒号“ :”)

let webButton = PassableUIButton(frame: CGRect(x:310, y:40, width:40, height:40))
webButton.setTitle("Visit",for: .normal)
webButton.addTarget(self, action: #selector(YourViewController.webButtonTouched(_:)), for:.touchUpInside)
webButton.params["myvalue"] = "bob"

然后终于在这里抓住了一切

@IBAction func webButtonTouched(_ sender: PassableUIButton) {
print(sender.params["myvalue"] ?? "")
}

You do this one time and use it throughout your project (you can even make the child class have a generic "object" and put whatever you like into the button!). Or use the example above to put an inexhaustible number of key/string params into the button.. Really useful for including things like urls, confirm message methodology etc

顺便说一句,重要的是,SO社区意识到,有整整一代的不良实践正在互联网上被大量的程序员剪切粘贴,这些程序员不理解/没有接受过教育/没有理解 object extensions的概念

Swift 4.2

结果:

testButton.on(.touchUpInside) { (sender, event) in
// You can use any reference initialized before the code block here
// You can access self by adding [weak self] before (sender, event)
// You can then either make self strong by using a guard statement or use a optional operator (?)
print("user did press test button")
}

在文件 UIButton+Events.swift中,我为 UIButton创建了一个扩展方法,它将 UIControl.Event绑定到一个名为 EventHandler的完成处理程序:

import UIKit


fileprivate var bindedEvents: [UIButton:EventBinder] = [:]


fileprivate class EventBinder {


let event: UIControl.Event
let button: UIButton
let handler: UIButton.EventHandler
let selector: Selector


required init(
_ event: UIControl.Event,
on button: UIButton,
withHandler handler: @escaping UIButton.EventHandler
) {
self.event = event
self.button = button
self.handler = handler
self.selector = #selector(performEvent(on:ofType:))
button.addTarget(self, action: self.selector, for: event)
}


deinit {
button.removeTarget(self, action: selector, for: event)
if let index = bindedEvents.index(forKey: button) {
bindedEvents.remove(at: index)
}
}
}


private extension EventBinder {


@objc func performEvent(on sender: UIButton, ofType event: UIControl.Event) {
handler(sender, event)
}
}


extension UIButton {


typealias EventHandler = (UIButton, UIControl.Event) -> Void


func on(_ event: UIControl.Event, handler: @escaping EventHandler) {
bindedEvents[self] = EventBinder(event, on: self, withHandler: handler)
}
}

我之所以使用自定义类来绑定事件,是为了能够在按钮去初始化后释放引用。这将防止可能发生的内存泄漏。这在 UIButton的扩展中是不可能的,因为我不允许实现一个属性,也不允许实现 deinit方法。

斯威夫特5.0代码

我使用 Button.tag,但是如果我有很多类型的选项,它将是一个很长的开关案例。

theButton.addTarget(self, action: #selector(theFunc), for: .touchUpInside)
theButton.frame.name = "myParameter"

.

@objc func theFunc(sender:UIButton){
print(sender.frame.name)
}
button.tag = indexPath.row
button.addTarget(self, action: "buttonClicked:",
forControlEvents: UIControlEvents.TouchUpInside)
cell.accessoryView = button;

按钮标记可以帮助您从数组/字典中检索专用记录

可能有点过了,但你就不能用个协议吗?那么就真的不需要传入参数,因为您应该可以访问符合条件的类中的属性。

protocol ButtonActionDelegate {
func buttonClicked()
}


class SomeClassWithSomeButton: ButtonActionDelegate {
let button = UIButton
button.addTarget(self, action: "buttonClicked", forControlEvents: UIControlEvents.TouchUpInside)


func buttonClicked() {
//Do specific action
}
}