首页 > 解决方案 > 使用扩展创建可点击的 UIImageView

问题描述

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

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

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

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 的子类是否正确?如果可能的话,我想尽量避免这种情况,因为如果我想把它变成一个框架或库或其他东西,子类不能很好地集成到接口构建器中,开发人员必须添加额外的步骤来改变他们所有的图像视图的类。如果可能的话,我认为避免这种情况会很棒。

标签: iosswiftuiimageviewclickableswift-extensions

解决方案


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

这是一个(经过测试的)解决方案,它子类UITapGestureRecognizer化以使可UIGestureRecognizer识别,然后搜索self.gestureRecognizersfirst(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")
    }
}

推荐阅读