Swift - 如何将点击手势添加到 UIViews 数组?
Posted
技术标签:
【中文标题】Swift - 如何将点击手势添加到 UIViews 数组?【英文标题】:Swift - How to add tap gesture to array of UIViews? 【发布时间】:2019-01-21 14:57:15 【问题描述】:希望将点击手势添加到 UIView
s 数组中 - 没有成功。在此阶段似乎无法识别 Tap。
在下面的代码(摘录)中:
在主视图上显示一系列PlayingCardViews
(每个UIView
)。
集合为一个数组:cardView
。
需要能够独立点击每个PlayingCardView
(然后能够识别哪个被点击了)。
@IBOutlet private var cardView: [PlayingCardView]!
override func viewDidLoad()
super.viewDidLoad()
let tap = UITapGestureRecognizer(target: self, action: #selector(tapCard(sender: )))
for index in cardView.indices
cardView[index].isUserInteractionEnabled = true
cardView[index].addGestureRecognizer(tap)
cardView[index].tag = index
@objc func tapCard (sender: UITapGestureRecognizer)
if sender.state == .ended
let cardNumber = sender.view.tag
print("View tapped !")
【问题讨论】:
那么tapCard
函数是否被调用了?顺便说一句,您还没有使用 cardNumber
属性。
正确@DávidPásztor:'tapCard' 函数未被调用(即,当我在 IB 上点击任何 PlayingCardView 时,控制台上没有打印任何内容。关于 'cardNumber',您也是正确的,尚未使用但打算以后再说。
你不能确定函数没有被print
语句没有被执行,因为你将它嵌套在if
语句中:) 你应该使用调试器来检查函数实际上是否被调用(或在if
语句之外放置一个打印语句),但if
语句似乎是不必要的。
删除了 if 语句,只保留了函数中的 print。仍然没有打印到控制台。
您当前案例中的点击将仅添加到最后一个视图中
【参考方案1】:
你需要
@objc func tapCard (sender: UITapGestureRecognizer)
let clickedView = cardView[sender.view!.tag]
print("View tapped !" , clickedView )
这里不需要检查状态,因为这种手势类型的方法只调用一次,而且每个视图都应该有一个单独的点击,所以在for循环中创建它
for index in cardView.indices
let tap = UITapGestureRecognizer(target: self, action: #selector(tapCard(sender: )))
【讨论】:
谢谢@sh_khan。只要我可以通过点击手势调用“tapCard”函数,就会尝试这样做。 谢谢@sh_khan。这似乎确实有效......在这里测试并将很快确认。另外,顺便说一句:在哪里有 for 循环创建点击手势的最佳位置:在 viewDidLoad (如上)或 cardView 声明中的 didSet 中?这有什么不同吗 ?一个更合适吗? (很快恢复以确认我是否能够按照您的解决方案进行修复) 两种情况都可以,但我推荐viewDidLoad
经过测试,似乎有效,@sh_khan。谢谢!【参考方案2】:
我不会推荐所选答案。因为在循环中创建一个 tapGesture 数组对我来说没有意义。最好在 PlaycardView 中添加手势。
相反,应使用 UICollectionView 设计此类布局。如果您需要自定义布局并且想要使用滚动视图甚至 UIView,那么更好的方法是创建单个手势识别器并添加到超级视图。
使用点击手势,您可以获得点击的位置,然后您可以使用该位置获取 selectedView。
请参考以下示例:
import UIKit
class PlayCardView: UIView
override init(frame: CGRect)
super.init(frame: frame)
backgroundColor = UIColor.red
required init?(coder aDecoder: NSCoder)
super.init(coder: aDecoder)
backgroundColor = UIColor.red
class SingleTapGestureForMultiView: UIViewController
var viewArray: [UIView]!
var scrollView: UIScrollView!
override func viewDidLoad()
super.viewDidLoad()
scrollView = UIScrollView(frame: UIScreen.main.bounds)
view.addSubview(scrollView)
let tapGesture = UITapGestureRecognizer(target: self,
action: #selector(tapGetsure(_:)))
scrollView.addGestureRecognizer(tapGesture)
addSubviews()
func addSubviews()
var subView: PlayCardView
let width = UIScreen.main.bounds.width;
let height = UIScreen.main.bounds.height;
let spacing: CGFloat = 8.0
let noOfViewsInARow = 3
let viewWidth = (width - (CGFloat(noOfViewsInARow+1) * spacing))/CGFloat(noOfViewsInARow)
let viewHeight = (height - (CGFloat(noOfViewsInARow+1) * spacing))/CGFloat(noOfViewsInARow)
var yCordinate = spacing
var xCordinate = spacing
for index in 0..<20
subView = PlayCardView(frame: CGRect(x: xCordinate, y: yCordinate, width: viewWidth, height: viewHeight))
subView.tag = index
xCordinate += viewWidth + spacing
if xCordinate > width
xCordinate = spacing
yCordinate += viewHeight + spacing
scrollView.addSubview(subView)
scrollView.contentSize = CGSize(width: width, height: yCordinate)
@objc
func tapGetsure(_ gesture: UITapGestureRecognizer)
let location = gesture.location(in: scrollView)
print("location = \(location)")
var locationInView = CGPoint.zero
let subViews = scrollView.subviews
for subView in subViews
//check if it subclass of PlayCardView
locationInView = subView.convert(location, from: scrollView)
if subView.isKind(of: PlayCardView.self)
if subView.point(inside: locationInView, with: nil)
// this view contains that point
print("Subview at \(subView.tag) tapped");
break;
【讨论】:
感谢@ankur 提供替代解决方案。【参考方案3】:您可以尝试将视图控制器作为参数传递给视图,以便它们可以从视图调用父视图控制器上的函数。要减少内存,您可以使用协议。例如
protocol testViewControllerDelegate: class
func viewTapped(view: UIView)
class testClass: testViewControllerDelegate
@IBOutlet private var cardView: [PlayingCardView]!
override func viewDidLoad()
super.viewDidLoad()
for cardView in self.cardView
cardView.fatherVC = self
func viewTapped(view: UIView)
// the view that tapped is passed ass parameter
class PlayingCardView: UIView
weak var fatherVC: testViewControllerDelegate?
override func awakeFromNib()
super.awakeFromNib()
let gr = UITapGestureRecognizer(target: self, action: #selector(self.viewDidTap))
self.addGestureRecognizer(gr)
@objc func viewDidTap()
fatherVC?.viewTapped(view: self)
【讨论】:
谢谢,去看看。还测试了来自@sh_khan 的解决方案,似乎有效。以上是关于Swift - 如何将点击手势添加到 UIViews 数组?的主要内容,如果未能解决你的问题,请参考以下文章
如何将手势识别器添加到collectionview单元格中的uiview