UITapGestureRecognizer与arrangedSubviews问题:点击图片改边框报错
问题与解决方案:UIStackView图片点击修改边框颜色报错处理
错误原因分析
报错-[__NSArray0 tapOnView]: unrecognized selector sent to instance的核心问题是:你将arrangedImages(NSArray类型)设置为UITapGestureRecognizer的target,但数组根本没有tapOnView方法。此外代码还有其他逻辑缺陷:
- UIImageView默认关闭用户交互,手势无法触发
- 给整个视图加手势而非单个图片,无法定位点击的目标
- 手势未关联到视图就尝试获取tag,值为nil
- 协议方法未传递点击信息,无法针对性修改边框
修改后的完整代码实现
1. 修正图片配置方法(给每个图片加单独手势)
func configureMediaViewer(withImages images: [String]) { // 先清空旧视图,避免重复添加 mainHStack.arrangedSubviews.forEach { $0.removeFromSuperview() } for (index, image) in images.enumerated() { let imageView = UIImageView() imageView.contentMode = .scaleAspectFill imageView.layer.cornerRadius = 8 imageView.clipsToBounds = true imageView.tag = index // 必须开启用户交互,UIImageView默认关闭 imageView.isUserInteractionEnabled = true imageView.setImage(imageUrl: image) mainHStack.addArrangedSubview(imageView) imageView.snp.makeConstraints { make in make.width.height.equalTo(60) } // 给每张图片单独添加点击手势 let tap = UITapGestureRecognizer(target: self, action: #selector(tapOnView(_:))) imageView.addGestureRecognizer(tap) } }
2. 修改点击响应方法(处理边框逻辑+通知代理)
@objc func tapOnView(_ gesture: UITapGestureRecognizer) { guard let tappedImageView = gesture.view as? UIImageView else { return } // 重置所有图片的边框,保证只有当前点击的图片有橙色边框 mainHStack.arrangedSubviews.forEach { view in view.layer.borderWidth = 0 } // 设置当前点击图片的边框样式 tappedImageView.layer.borderWidth = 1 tappedImageView.layer.borderColor = UIColor.orange.cgColor // 通知代理点击的图片索引 delegate?.tapOnView(at: tappedImageView.tag) }
3. 更新协议定义(传递点击索引)
protocol PhotosViewProtocol: AnyObject { func tapOnView(at index: Int) }
4. 修正主VC代理实现
extension MediaViewerViewController: PhotosViewProtocol { func tapOnView(at index: Int) { print("点击了第\(index)张图片") // 可在此添加其他业务逻辑 } }
5. 移除无效方法
删除原来的tapOnMediaView()方法,其逻辑完全错误,无需保留。
关键修改点总结
- 给每个UIImageView单独绑定手势,target设为当前控制器(self)而非数组
- 开启UIImageView的
isUserInteractionEnabled,否则手势无法触发 - 通过手势参数获取点击的视图,精准定位目标
- 重置所有边框再设置当前点击项,保证选中状态唯一
- 协议方法传递点击索引,让代理能获取具体点击位置
内容的提问来源于stack exchange,提问作者kesape
相关产品推荐
相关产品推荐

