使用扩展创建可点击的UIImageView

时间:2018-08-18 18:51:57

标签: ios swift uiimageview clickable swift-extensions

我有以下Swift代码。

extension UIImageView {
    func enableClickablePrint() {
        let imageTap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
        self.addGestureRecognizer(imageTap)
        self.isUserInteractionEnabled = true
    }
    func disableClickablePrint() {
        // HERE
    }
    func toggleClickablePrint() {
        // HERE
    }

    @objc fileprivate func imageTapped(_ sender: UITapGestureRecognizer) {
        print("Image tapped")
    }
}

我遇到的问题是如何填写disableClickablePrinttoggleClickablePrint函数。

我希望能够执行以下操作。

extension UIImageView {
    var imageTap: UITapGestureRecognizer?
    func enableClickablePrint() {
        imageTap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
        self.addGestureRecognizer(imageTap)
        self.isUserInteractionEnabled = true
    }
    func disableClickablePrint() {
        if let theImageTap = imageTap {
            self.removeGestureRecognizer(theImageTap)
            imageTap = nil
        }
    }
    func toggleClickablePrint() {
        if let theImageTap = imageTap {
            disableClickablePrint()
        } else {
            enableClickablePrint()
        }
    }

    @objc fileprivate func imageTapped(_ sender: UITapGestureRecognizer) {
        print("Image tapped")
    }
}

但是,当然,问题在于您无法像我想要的那样将属性存储在扩展名中。

无论如何要实现这一目标?我想尽量保持清洁,除非绝对需要,否则不要采用任何花哨的技巧。

将其转换为UIImageView的子类是否正确?我想尽量避免这种情况,只是因为如果我想将其转换为框架或库之类的东西,则子类就不能很好地集成到接口构建器中,而开发人员将不得不添加额外的步骤来更改他们所有图像视图的类别。我认为,如果可能的话,应该避免这种情况。

3 个答案:

答案 0 :(得分:3)

您的问题是您需要能够识别添加的UIGestureRecognizer,但不能将其存储在属性中。

这是一个(经过测试的)解决方案,该解决方案将UITapGestureRecognizer子类化以使UIGestureRecognizer可识别,然后用self.gestureRecognizers搜索first(where:)以查看是否已添加:

extension UIImageView {

    class _CFTapGestureRecognizer : UITapGestureRecognizer { }

    private var _imageTap: _CFTapGestureRecognizer? { return self.gestureRecognizers?.first(where: { $0 is _CFTapGestureRecognizer }) as? _CFTapGestureRecognizer }

    func enableClickablePrint() {
        // Only enable once
        if _imageTap == nil {
            let imageTap = _CFTapGestureRecognizer(target: self, action: #selector(imageTapped))
            self.addGestureRecognizer(imageTap)
            self.isUserInteractionEnabled = true
        }
    }

    func disableClickablePrint() {
        if let theImageTap = _imageTap {
            self.removeGestureRecognizer(theImageTap)
        }
    }

    func toggleClickablePrint() {
        if _imageTap == nil {
            enableClickablePrint()
        } else {
            disableClickablePrint()
        }
    }

    @objc fileprivate func imageTapped(_ sender: UITapGestureRecognizer) {
        print("Image tapped")
    }
}

答案 1 :(得分:-1)

您可以使用getter / setter来设置扩展变量:

extension UIImageView {

var tap: UITapGestureRecognizer {
    get {
        return //the created tap
    }
    set(value) {
        print(value)
    }
}

}

答案 2 :(得分:-1)

由于swift中的扩展不能包含存储的属性,因此可以采用以下解决方案:

第一个最常用的解决方法是通过使用objc_getAssociatedObjectobjc_setAssociatedObject函数来使用Objective_C运行时。

好的,这是一个很好的解决方案,但是如果有纯粹的快速方法可以做到这一点,那么为什么呢!

在扩展名中,使用您要使用的字段定义结构,例如UITapGestureRecognizer

提示以私有方式创建此结构当然,不需要任何人访问它。

然后定义一个将使用此结构的计算属性。...

通过此操作,您已经达到了所需的目的,并且根本没有使用Objective-C。

示例:

extension UIImageView {
    private struct TapGestureHelper{
        static var tapGestureRecognizer : UITapGestureRecognizer?
    }

    var imageTap: UITapGestureRecognizer?{
        get {
            return TapGestureHelper.tapGestureRecognizer
        }
        set {
            TapGestureHelper.tapGestureRecognizer = newValue
        }
    }

    func enableClickablePrint() {
        imageTap = UITapGestureRecognizer(target: self, action: #selector(imageTapped))
        self.addGestureRecognizer(imageTap!)
        self.isUserInteractionEnabled = true
    }

    func disableClickablePrint() {
          guard let gesture = self.gestureRecognizers?.first else {
              return
          }
          self.removeGestureRecognizer(gesture)
          self.imageTap = nil
    }

    func toggleClickablePrint() {
        if let theImageTap = imageTap {
            disableClickablePrint()
        } else {
            enableClickablePrint()
        }
    }

    @objc fileprivate func imageTapped(_ sender: UITapGestureRecognizer) {
        print("Image tapped")
    }
}