繁体   English   中英

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

[英]How to pass touchUpInside function as parameter in swift?

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

使用未解析的标识符 'myFuncName(sender:)'

我的代码(您可以将其粘贴到 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)
    }
}

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

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?()
    }
}
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 )。 在这里,我们说我想在button接收到.touchUpInside事件时调用ViewController类中的buttonTapped方法。

好吧,我认为这种方法有问题。 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()
    }

}
class VC: UIViewController {

    //Outlet of your custom button.
    @IBOutlet weak var button: CustomButton!    

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

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

解释:

  1. 在上面的代码中,我们对 UIButton 进行了子类化并在其中声明了一个属性。 这是一种返回 void 的函数类型。
  2. 然后我们将目标添加到 UIButton 子类的函数中。 每次点击按钮时,都会执行“点击按钮”功能。
  3. 然后我们直接将函数赋值给属性“closure”。 (“var 闭包”是返回 void 的函数类型的属性。)

希望这会有所帮助。 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM