微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何向通用 UITapGestureRecognizer 添加参数?

如何解决如何向通用 UITapGestureRecognizer 添加参数?

问题是:我该如何制作一个通用版本的 UITapGestureRecognizer,以便我可以在我的应用中使用。

如果我不想传递任何参数,那就很简单了:

class ClickListener: UITapGestureRecognizer {
    var onClick : (() -> Void)? = nil
}


// MARK: UIView Extension
extension UIView {
    
    func setonClickListener(action :@escaping () -> Void){
        let tapRecogniser = ClickListener(target: self,action: #selector(onViewClicked(sender:)))
        tapRecogniser.onClick = action
        self.addGestureRecognizer(tapRecogniser)
    }
    
    @objc func onViewClicked(sender: ClickListener) {
        if let onClick = sender.onClick {
            onClick()
        }
    }
  
}

正如Sunneet Agrawal所做的那样。

问题是,我有时需要向这个函数传递参数。 例如,如果我想传递一个对象,我想这样做。然后我可以通过应用程序全局重用这个功能

我尝试的所有方法都不起作用,我可以提供一些这样的代码

class ClickListener<T: Any>: UITapGestureRecognizer {
    var onClick : (() -> Void)? = nil
    var clickedobject: Any
    
    override init(onClick: (() -> Void),clickedobject: Any,target: self,action: ???){
        self.onClick = onClick
        self.clickedobject = clickedobject
        super.init(target: self,action: ???)
    }
}

extension UIView {
    
    func setonClickListener(action :@escaping () -> Void){
        let tapRecogniser = ClickListener(// Init here)
        tapRecogniser.onClick = action( // parameter here)
        self.addGestureRecognizer(tapRecogniser)
    }
    
    @objc func onViewClicked(sender: ClickListener) {
        if let onClick = sender.onClick {
            onClick(// with parameter passed)
        }
    }
  
}

// Then in my VC

UIView.setonclickListener(action: anyFunction,clickedobject: anyObject)

但我在那里有点迷茫。

解决方法

首先,目标/动作模式的selector有两种固定形式:

  • 一个没有参数的函数
  • 带有一个参数的函数表示sender,即触发操作的对象。

但是您可以在子类中添加属性并在(自定义)init 方法中传递参数。

子类中的泛型与框架相抗衡,因此自定义字典(您也可以仅使用 Any)是更好的选择。

例如,除了目标和操作之外,该类还有一个 userInfo 字典和一个 onClick 闭包。 init 方法调用 super 来调用点击识别器的指定初始化器。

class ClickListener: UITapGestureRecognizer {
    var onClick : (() -> Void)?
    var userInfo: [String:Any]?
    
    init(target: Any?,action: Selector?,userInfo: [String:Any]? = nil,onClick: (() -> Void)? = nil) {
        self.userInfo = userInfo
        self.onClick = onClick
        super.init(target: target,action: action)
    }
}

你可以使用它

extension UIView {
    
    func setOnClickListener(action :@escaping () -> Void){
        let tapRecogniser = ClickListener(target: self,action: #selector(onViewClicked),userInfo: ["message":"Hello World"],onClick: action)
        self.addGestureRecognizer(tapRecogniser)
    }
    
    @objc func onViewClicked(_ sender: ClickListener) {
        if let userInfo = sender.userInfo,let message = userInfo["message"] as? String {
            print(message)
        }
        sender.onClick?()
    }
    
}

通用的实现是在 userInfo 闭包中传递 onClick

class ClickListener: UITapGestureRecognizer {
    var onClick : (([String:Any]?) -> Void)?
    var userInfo: [String:Any]?
    
    init(target: Any?,onClick: (([String:Any]?) -> Void)?) {
        self.userInfo = userInfo
        self.onClick = onClick
        super.init(target: target,action: action)
    }
}

extension UIView {
    
    func setOnClickListener(userInfo: [String:Any],action :@escaping ([String:Any]?) -> Void){
        let tapRecogniser = ClickListener(target: self,userInfo: userInfo,onClick: action)
        self.addGestureRecognizer(tapRecogniser)
    }
    
    @objc func onViewClicked(_ sender: ClickListener) {
        sender.onClick?(sender.userInfo)
    }
    
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。