如何使用静态函数中的UITapGestureRecognizer向标签添加点按功能

时间:2017-08-10 19:14:44

标签: ios swift xcode swift3

我需要动态地在我的应用中为labels添加点按功能(以打开网站),我在考虑在class内创建静态功能。我想在我的应用的任何ViewController中启动该功能。

我使用Swift 3完成了这个:

class Launcher {
    static func openWeb(label: UILabel, url: String) {
        func tapFunction(sender:UITapGestureRecognizer) {

            if #available(iOS 10.0, *) {
                UIApplication.shared.open(URL(string: url)!, options: [:], completionHandler: nil)
            } else {
                UIApplication.shared.openURL(URL(string: url)!)
            }
        }

        let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction))
        label.isUserInteractionEnabled = true
        label.addGestureRecognizer(tap)

        if #available(iOS 10.0, *) {
            UIApplication.shared.open(URL(string: url)!, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(URL(string: url)!)
        }

    }
}

但是不起作用,因为我在action: #selector(tapFunction)

中收到错误

错误Argument of '#selector' cannot refer to local function 'tapFunction(sender:)'

如果我在使用ViewController的{​​{1}}代码中使用此功能,请执行以下操作

内部action: #selector(myView.tapFunction)

viewDidLoad

let tap = UITapGestureRecognizer(target: self, action: #selector(MyViewController.tapFunction)) mylabel.isUserInteractionEnabled = true mylabel.addGestureRecognizer(tap)

内的分隔函数
ViewController

我想将此最后一个代码转换为func tapFunction(sender:UITapGestureRecognizer) { if #available(iOS 10.0, *) { UIApplication.shared.open(URL(string: url)!, options: [:], completionHandler: nil) } else { UIApplication.shared.openURL(URL(string: url)!) } } 内的静态函数,以便在任何Class中调用它。谢谢

3 个答案:

答案 0 :(得分:2)

应该与实例通信的方法不能是静态/类方法。这就是静态/类方法的含义;它是关于 - 故事中没有实例。因此,你提出的建议是不可能的,除非你把静态方法交给它应该与之交谈的实例。

就我个人而言,一个可打开的URL开放标签听起来像一个标签子类,然后这个功能就是该标签的实例方法。

答案 1 :(得分:2)

  

尝试使用扩展程序

解决此问题
extension UILabel {
    func openWeb(url: String) {
        let tap = UITapGestureRecognizer(target: self, action: #selector(tapFunction))
        self.isUserInteractionEnabled = true
        self.addGestureRecognizer(tap)

        openURL(url: url)
    }

    func tapFunction(sender:UITapGestureRecognizer) {
        openURL(url: "")
    }

    func openURL(url: String) {
        if #available(iOS 10.0, *) {
            UIApplication.shared.open(URL(string: url)!, options: [:], completionHandler: nil)
        } else {
            UIApplication.shared.openURL(URL(string: url)!)
        }
    }
}

let label = UILabel()
label.openWeb(url: "123")
  

要将链接存储到标签中,您可以使用与标签对象的关联。

答案 2 :(得分:1)

首先,您的方法存在一些常见问题。选择器通过消息传递工作。例如。 with UITapGestureRecognizer(target:, action:)调用方法的消息(action)将发送到变量(target)。

当您创建本地函数时,该函数是封闭函数的成员而不是包含的类或实例,因此您的方法明确无法工作。

即使它可以工作,它也会违反OOP和MVC设计原则。 Label不应该负责在点击时发生的事情,就像书的标题不负责打开书一样。

考虑到所有这些,这就是我解决问题的方法:

extension UIViewController {

    func addTapGesture(to view: UIView, with selector: Selector) {
        view.isUserInteractionEnabled = true
        view.addGestureRecognizer(UITapGestureRecognizer(target: view, action: selector))
    }
}

extension UIApplication {

    func open(urlString: String) {

        if #available(iOS 10.0, *) {
            open(URL(string: urlString)!, options: [:], completionHandler: nil)
        } else {
            openURL(URL(string: urlString)!)
        }
    }
}

class YourVC: UIViewController {

    var aLabel: UILabel? = nil

    func addTapGesture() {
        addTapGesture(to: aLabel!, with: #selector(tapGestureActivated))
    }

    func tapGestureActivated(gesture: UITapGestureRecognizer?) {
        UIApplication.shared.open(urlString: "YourURLHere")
    }
}

这抽象了样板,在使用时很简单,同时仍然正确地分离出Type责任并使用可在其他地方重复使用的通用功能。