如何在swift中传递touchUpInside函数作为参数?

时间:2018-01-28 23:31:45

标签: ios swift

我创建了一个动态UIButton,我想动态地将监听器设置为按钮。但我得到错误:

  

使用未解析的标识符' myFuncName(发件人:)'

我的代码(您可以将其粘贴到Xcode中并运行):

import UIKit

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

//        add my button
        let button = Btn()
        button.setListener(buttonTapped)
        view.addSubview(button)
    }

    @objc func buttonTapped() {
        print("tapped")
    }
}

//    -------------------------------
class Btn: UIControl {
    fileprivate let button: UIButton = {
        let swapButton = UIButton()
        let size = CGFloat(50)
        swapButton.frame.size = CGSize(width: size, height: size)
        swapButton.backgroundColor = UIColor.green

        return swapButton
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(button)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        addSubview(button)
    }

    func setListener(_ listener: @escaping () -> Void) {
        // Error - Use of unresolved identifier 'listener(sender:)'
        button.addTarget(self, action: #selector(listener(sender:)), for: .touchUpInside)
    }
}

3 个答案:

答案 0 :(得分:2)

#selector创建一个指向函数的Selector。如果要调用自定义侦听器代码块,则需要将其分配给Btn的实例var,然后从私有函数调用它。

let button = Btn()
button.listener = {
    // your closure here
}

class Btn: UIControl {
    weak var listener: (() -> Void)?

    override init(frame: CGRect) {
        super.init(frame: frame)
        addSubview(button)
        button.addTarget(self, action: #selector(buttonTapped(_:)), for: .touchUpInside)
    }

    @objc private func buttonTapped(_ sender: UIButton) {
        self.listener?()
    }
}

答案 1 :(得分:1)

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

//        add my button
        let button = Btn()
        self.addListener(to: button, using: #selector(buttonTapped))
        view.addSubview(button)
    }

    @objc func buttonTapped() {
        print("tapped")
    }

    func addListener(to button: UIButton, using handler: Selector) {
        button.addTarget(self, action: handler, for: .touchUpInside)
    }
}

以上代码是我相信你想要实现的。 addTarget方法的要点是告诉控件哪个类(目标;本例中为self),方法(操作)以及何时调用方法(.touchUpInside )。在这里,我们说我想在buttonTapped收到ViewController事件时在button班级中调用.touchUpInside方法。

答案 2 :(得分:1)

嗯,我认为这种方法有问题。 UIButton是UIControl的子类,你正试图做一些不合法的事情。简而言之,您正在父类本身中创建子类的对象。

解决方案:在我看来,你可能想要UIButton的子类而不是UIControl。例如。

class CustomButton:UIButton {

// Properties
var closure: () -> Void = {
    /// empty initialization
}

override func awakeFromNib() {
    super.awakeFromNib()
    self.addTarget(self, action: #selector(self.buttonTapped), for: .touchUpInside)
}


// methods and selectors
@objc func buttonTapped() {
    // Your Code.
    self.closure()
}

}

类VC:UIViewController {

//自定义按钮的插座。     @IBOutlet弱变量按钮:CustomButton!

override func viewDidLoad() {
    super.viewDidLoad()
    button.closure = self.buttonTapped
}

public func buttonTapped(){
    print("Code Works...")
}    

}

说明:  1.在上面的代码中,我们对UIButton进行了分类,并在其中声明了一个属性。这是一种返回void的函数。

  1. 然后我们将目标添加到UIButton子类的函数中。每次点击按钮时,都会执行“按钮点按”功能。

  2. 然后我们直接将函数分配给属性“closure”。 ('var closure'是返回void的函数类型的属性。)

  3. 希望这会有所帮助。 :)