使用扩展创建可点击的 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")
}
}

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

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

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

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")
}
}

我已经使用这个扩展程序多年了,它不仅可以使用图像,还可以用于任何视图。

extension UIView {
func addTapGuesture(target: Any, action: Selector) {
let tap = UITapGestureRecognizer(target: target, action: action)
tap.numberOfTapsRequired = 1
addGestureRecognizer(tap)
isUserInteractionEnabled = true
}
}

用法:

imageView.addTapGuesture(target: self, action: #selector(imageTapped))
@objc func imageTapped() {
print("Tapped")
}

您可以使用getter/setter创建一个扩展变量:

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

由于 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")
}
}

相关内容

  • 没有找到相关文章

最新更新