簡體   English   中英

將參數附加到 Swift 中的 button.addTarget 操作

[英]Attach parameter to button.addTarget action in Swift

我試圖將一個額外的參數傳遞給 buttonClicked 操作,但無法確定 Swift 中的語法應該是什么。

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

任何我的 buttonClicked 方法:

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

有人有什么想法嗎?

謝謝你的幫助。

您不能在addTarget:傳遞自定義參數。另一種方法是設置按鈕的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")
}

如果你想向 buttonClicked 方法發送額外的參數,例如 indexPath 或 urlString,你可以子類化 UIButton:

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

確保將身份檢查器中按鈕的類更改為 subclassedUIButton。 您可以使用sender.indexPathsender.urlString訪問 buttonClicked 方法中的參數。

注意:如果您的按鈕位於單元格內,您可以在 cellForRowAtIndexPath 方法(創建按鈕的位置)中設置這些附加參數的值。

我感謝每個人都說使用標簽,但實際上您需要擴展 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"] ?? "")
}

您執行一次並在整個項目中使用它(您甚至可以讓子類擁有一個通用的“對象”並將您喜歡的任何內容放入按鈕中!)。 或者使用上面的示例將無窮無盡的鍵/字符串參數放入按鈕中。對於包含諸如 url、確認消息方法等內容非常有用

順便說一句, SO社區意識到這一點很重要,有大量不理解/沒有被教導/錯過重點的程序員正在互聯網上剪切和粘貼整整一代的不良做法。 object extensions的概念

對於 Swift 3.0,您可以使用以下內容

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

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

}

斯威夫特 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方法。

在Swift 3中創建一個這樣的選擇器:

button.addTarget(self, action: #selector(ViewController.multipleParamSelector(_:secondParams:)), for: .touchUpInside)

並抓住這樣的事件:

func multipleParamSelector(_ sender: AnyObject, secondParams: AnyObject) {

}

如果你有像我一樣的按鈕循環,你可以嘗試這樣的事情

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 語言的 swift 函數的語法。

@objc func deleteAction(sender: UIButton) {
}

創建一些工作按鈕:

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

Swift 5.0 代碼

我使用 theButton.tag 但如果我有很多類型的選項,它是很長的開關盒。

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

.

@objc func theFunc(sender:UIButton){ 
print(sender.frame.name)
}

這是一個更重要的評論。 共享開箱即用的 sytanx 引用。 對於黑客解決方案,請查看其他答案。

根據 Apple 的文檔,Action Method Definitions必須是這三個中的一個。 其他的都是不接受的。

@IBAction func doSomething()
@IBAction func doSomething(sender: UIButton)
@IBAction func doSomething(sender: UIButton, forEvent event: UIEvent)

對於 Swift 2.X 及更高版本

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

斯威夫特 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
}

您可以在“userinfo”中發送值並將其用作函數中的參數。

button.tag = indexPath.row
button.addTarget(self, action: "buttonClicked:", 
    forControlEvents: UIControlEvents.TouchUpInside)
cell.accessoryView = button;

按鈕標簽可以幫助您從數組/字典中檢索專用記錄

可能有點矯枉過正,但你不能為此使用協議嗎? 那么就真的不需要傳入參數了,因為你應該可以訪問符合 class 的屬性。

protocol ButtonActionDelegate {
      func buttonClicked()
}

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

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

雖然您不能按照您建議的方式傳遞參數(使用addTarget ),但您可以使用addAction ,您可以在其中使用您想要的任何參數調用任何其他 function :

let btnAuto = UIButton(type: .system)
    btnAuto.frame = CGRect(x:0, y:0 , width:200, height:20)
    btnAuto.backgroundColor = .blue
    btnAuto.addAction(
        UIAction { _ in
            print("This gets printed when the button is pressed")
            dothis(param1, param2)
        }, for: .touchUpInside)
    self.view.addSubview(btnAuto)

當您以編程方式創建一系列按鈕並希望每個按鈕執行不同的操作時,這特別有用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM