代码之家  ›  专栏  ›  技术社区  ›  Charlie Fish

使用扩展名创建可单击的UIImageView

  •  2
  • Charlie Fish  · 技术社区  · 6 年前

    我有以下的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")
        }
    }
    

    disableClickablePrint toggleClickablePrint 功能。

    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 回复  |  直到 6 年前
        1
  •  3
  •   vacawama    6 年前

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

    下面是一个(经过测试的)解决方案 UITapGestureRecognizer 手势识别器 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")
        }
    }
    
        2
  •  -1
  •   Pranav Wadhwa    6 年前

    可以使用getter/setter生成扩展变量:

    extension UIImageView {
    
    var tap: UITapGestureRecognizer {
        get {
            return //the created tap
        }
        set(value) {
            print(value)
        }
    }
    
    }
    
        3
  •  -1
  •   mojtaba al moussawi    6 年前

    由于swift中的扩展不能包含存储的属性,以下是解决方案:

    objc_getAssociatedObject objc_setAssociatedObject

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

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

    将此结构创建为private当然不需要任何人来访问它。

    通过这样做,你已经达到了你所需要的,而你根本不用目标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")
        }
    }