如何将闭包作为动作传递给添加到 UIView 的点击手势?

Swi*_*ing 1 closures ios uitapgesturerecognizer swift

我想要一个 UIView 上的点击函数,但我不知道如何在函数的第一张图片中传递该闭包:

在此处输入图片说明

在此处输入图片说明

Ahm*_*d F 7

首先:我强烈建议在您的问题中添加代码片段而不是屏幕截图。

您需要Selector为 action 参数传递 aUITapGestureRecognizer而不是() -> ()闭包:

extension UIView {
    func onClick(target: Any, _ selector: Selector) {
        isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: target, action: selector)
        addGestureRecognizer(tap)
    }
}
Run Code Online (Sandbox Code Playgroud)

另外,请记住,在这一点上,你必须设置相应targettap实例,这意味着它是不是 selfUIView扩展(如在你的代码中实现); 相反,您必须将其作为参数传递给onClick方法。

用法:

在您的 ViewController 中:

likesImg.onClick(target: self, #selector(likesImgClicked))

@objc private func likesImgClicked() {
    print(#function)
}
Run Code Online (Sandbox Code Playgroud)

当说likesImg.onClick(target: selfself这里是指 ViewController 本身,而不是UIView扩展,这是正确的目标,因为likesImgClicked在 ViewController 中实现而不是在UIView扩展中。


更新:

如果你坚持通过闭包的方法,你可以按照这个解决方案:

将您的 UIView 扩展实现为:

extension UIView {
    private struct OnClickHolder {
        static var _closure:()->() = {}
    }

    private var onClickClosure: () -> () {
        get { return OnClickHolder._closure }
        set { OnClickHolder._closure = newValue }
    }


    func onClick(target: Any, _ selector: Selector) {
        isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: selector)
        addGestureRecognizer(tap)
    }

    func onClick(closure: @escaping ()->()) {
        self.onClickClosure = closure

        isUserInteractionEnabled = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(onClickAction))
        addGestureRecognizer(tap)
    }

    @objc private func onClickAction() {
        onClickClosure()
    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

在您的 ViewController 中:

likesImg.onClick {
    print("Hello!!")
}
Run Code Online (Sandbox Code Playgroud)

重要的:

感谢@Josh Caswell提供以下说明:

请注意,私有结构为整个程序提供了一个存储位置。如果您尝试在多个视图上设置处理程序,第二个将覆盖第一个。

  • 请注意,私有结构为您提供了一个*用于整个程序*的存储位置。如果您尝试在多个视图上设置处理程序,第二个将覆盖第一个。 (2认同)

Ser*_*gio 5

我刚刚根据一些答案重新发明了快速点击监听器 android 风格。使用起来非常简单:

yourView.setClickListener {
    // do some actions here!
}
Run Code Online (Sandbox Code Playgroud)

将其添加到您的扩展文件中:

final class ClickListener: UITapGestureRecognizer {
    private var action: () -> Void

    init(_ action: @escaping () -> Void) {
        self.action = action
        super.init(target: nil, action: nil)
        self.addTarget(self, action: #selector(execute))
    }

    @objc private func execute() {
        action()
    }
}

extension UIView {
    func setClickListener(_ action: @escaping () -> Void) {
        self.isUserInteractionEnabled = true
        let click = ClickListener(action)
        self.addGestureRecognizer(click)
    }
}
Run Code Online (Sandbox Code Playgroud)