如何为UIImageView添加标识符以跳转至对应详情视图控制器?
问题描述
我有一个存储独立UIImage的数组,正通过UIImageView展示其中图片。希望为这些图片添加标识符,点击后能跳转至包含对应图片相关具体数据的视图控制器。不想用gesture.view.tag的方案,也不想创建额外视图,有没有可行的方法?
现有代码
class Orders2ViewController: UIViewController, OrdersBaseCoordinated { var orderList: [OrderInfo] = [OrderInfo( itemImage: UIImage(named: "printer.jpeg")!, itemSKU: 12567), OrderInfo(itemImage: UIImage(named: "ipad.jpeg")!, itemSKU: 34521), OrderInfo( itemImage: UIImage(named: "hoodie.jpeg")!, itemSKU: 93620)] lazy var someImageView: UIImageView = { let theImageView = UIImageView() let tap = UITapGestureRecognizer(target: self, action: #selector(Orders2ViewController.tappedMe)) theImageView.addGestureRecognizer(tap) theImageView.isUserInteractionEnabled = true theImageView.image = orderList[selectedIndex].itemImage theImageView.translatesAutoresizingMaskIntoConstraints = false return theImageView }() @objc func tappedMe(sender: UITapGestureRecognizer) { coordinator?.passImageData(j: ) } }
可行解决方案
方法1:用关联对象给UIImageView绑定数据
可以通过Objective-C的关联对象机制,直接给UIImageView绑定对应的OrderInfo或SKU,无需额外视图或tag。
- 先导入
objc/runtime并给UIImageView扩展关联属性:
import ObjectiveC private var AssociatedObjectKey: UInt8 = 0 extension UIImageView { var associatedOrderInfo: OrderInfo? { get { return objc_getAssociatedObject(self, &AssociatedObjectKey) as? OrderInfo } set { objc_setAssociatedObject(self, &AssociatedObjectKey, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } }
- 创建
someImageView时绑定对应的数据:
lazy var someImageView: UIImageView = { let theImageView = UIImageView() let tap = UITapGestureRecognizer(target: self, action: #selector(tappedMe)) theImageView.addGestureRecognizer(tap) theImageView.isUserInteractionEnabled = true let selectedOrder = orderList[selectedIndex] theImageView.image = selectedOrder.itemImage theImageView.associatedOrderInfo = selectedOrder // 绑定对应的OrderInfo theImageView.translatesAutoresizingMaskIntoConstraints = false return theImageView }()
- 在点击方法中取出绑定的数据:
@objc func tappedMe(sender: UITapGestureRecognizer) { guard let imageView = sender.view as? UIImageView, let targetOrder = imageView.associatedOrderInfo else { return } coordinator?.passImageData(j: targetOrder.itemSKU) // 传递SKU或整个OrderInfo }
方法2:自定义手势识别器携带数据
直接自定义UITapGestureRecognizer,把需要的标识符(SKU或OrderInfo)存在手势对象里,不依赖视图属性。
- 定义自定义手势类:
class OrderTapGestureRecognizer: UITapGestureRecognizer { var targetSKU: Int? var targetOrder: OrderInfo? }
- 创建手势时赋值数据:
lazy var someImageView: UIImageView = { let theImageView = UIImageView() let tap = OrderTapGestureRecognizer(target: self, action: #selector(tappedMe)) let selectedOrder = orderList[selectedIndex] tap.targetSKU = selectedOrder.itemSKU // 存储SKU tap.targetOrder = selectedOrder // 也可以存储整个OrderInfo对象 theImageView.addGestureRecognizer(tap) theImageView.isUserInteractionEnabled = true theImageView.image = selectedOrder.itemImage theImageView.translatesAutoresizingMaskIntoConstraints = false return theImageView }()
- 在点击方法中读取手势里的数据:
@objc func tappedMe(sender: UITapGestureRecognizer) { guard let orderTap = sender as? OrderTapGestureRecognizer, let sku = orderTap.targetSKU else { return } coordinator?.passImageData(j: sku) }
方法3:用闭包替代目标动作模式
不用目标动作模式,直接给手势绑定闭包,创建时就能直接拿到对应的数据,连点击方法都可以省略。
- 给
UITapGestureRecognizer添加闭包扩展:
extension UITapGestureRecognizer { convenience init(tapHandler: @escaping () -> Void) { self.init() self.addTarget(ClosureSleeve(closure: tapHandler), action: #selector(ClosureSleeve.invoke)) } } class ClosureSleeve: NSObject { let closure: () -> Void init(closure: @escaping () -> Void) { self.closure = closure super.init() } @objc func invoke() { closure() } }
- 创建手势时直接在闭包里处理跳转:
lazy var someImageView: UIImageView = { let theImageView = UIImageView() let selectedOrder = orderList[selectedIndex] // 直接用闭包处理点击逻辑,上下文直接拿到selectedOrder let tap = UITapGestureRecognizer { [weak self] in self?.coordinator?.passImageData(j: selectedOrder.itemSKU) } theImageView.addGestureRecognizer(tap) theImageView.isUserInteractionEnabled = true theImageView.image = selectedOrder.itemImage theImageView.translatesAutoresizingMaskIntoConstraints = false return theImageView }()
内容的提问来源于stack exchange,提问作者Tom Brooke
相关产品推荐
相关产品推荐

