Ios Swift-如何将点击手势添加到UIView数组中?

Ios Swift-如何将点击手势添加到UIView数组中?,ios,swift,uitapgesturerecognizer,Ios,Swift,Uitapgesturerecognizer,正在向UIViews数组添加点击手势,但未成功。Tap在现阶段似乎未被认可 在下面的代码(摘录)中: 在主视图上显示一系列播放卡片视图(每个都是ui视图)。 组合为一个数组:cardwiew。 需要能够独立点击每个播放卡片视图(然后能够识别点击的是哪一个) 你需要 @objc func tapCard (sender: UITapGestureRecognizer) { let clickedView = cardView[sender.view!.tag] print(

正在向
UIView
s数组添加点击手势,但未成功。Tap在现阶段似乎未被认可

在下面的代码(摘录)中: 在主视图上显示一系列
播放卡片视图
(每个都是
ui视图
)。 组合为一个数组:
cardwiew
。 需要能够独立点击每个
播放卡片视图
(然后能够识别点击的是哪一个)

你需要

@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: )))

您可以尝试将视图控制器作为参数传递给视图,以便它们可以从视图调用父视图控制器上的函数。为了减少内存,可以使用协议。e、 x

    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 {

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

我不推荐所选答案。因为在循环中创建一个tapperstate数组对我来说没有意义。最好在PlaycardView中添加手势

相反,应该使用UICollectionView设计此类布局。如果您需要自定义布局,并且希望使用scrollView甚至UIView,那么更好的方法是创建单手势识别器并添加到superview

使用点击手势,您可以获得点击的位置,然后可以使用该位置获得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;
                }
            }

        }

    }

}
导入UIKit
类PlayCardView:UIView{
重写初始化(帧:CGRect){
super.init(frame:frame)
backgroundColor=UIColor.red
}
必需的初始化?(编码器aDecoder:NSCoder){
super.init(编码者:aDecoder)
backgroundColor=UIColor.red
}
}
类SingleTapGestureForMultiView:UIViewController{
var viewArray:[UIView]!
var scrollView:UIScrollView!
重写func viewDidLoad(){
super.viewDidLoad()
scrollView=UIScrollView(框架:UIScreen.main.bounds)
view.addSubview(滚动视图)
让Tap手势=UITapGestureRecognitor(目标:自我,
操作:#选择器(点击GetSure(#:))
scrollView.AddGestureRecognitor(点击手势)
添加子视图()
}
func addSubviews(){
var子视图:PlayCardView
让宽度=UIScreen.main.bounds.width;
让高度=UIScreen.main.bounds.height;
let间距:CGFloat=8.0
设noOfViewsInARow=3
设viewWidth=(宽度-(CGFloat(noOfViewsInARow+1)*间距))/CGFloat(noOfViewsInARow)
让viewHeight=(高度-(CGFloat(noOfViewsInARow+1)*间距))/CGFloat(noOfViewsInARow)
变量Y坐标=间距
var xCOLUME=间距
对于0..width中的索引{
xcoordina=间距
Y坐标+=视图高度+间距
}
scrollView.addSubview(子视图)
}
scrollView.contentSize=CGSize(宽度:宽度,高度:Y坐标)
}
@objc
func-tapGetsure(uu手势:UITapGestureRecognizer){
让位置=手势。位置(在:滚动视图中)
打印(“位置=\(位置)”)
var locationInView=CGPoint.zero
让子视图=滚动视图。子视图
用于子视图中的子视图{
//检查是否为PlayCardView的子类
locationInView=subView.convert(位置,发件人:scrollView)
如果subView.isKind(类型:PlayCardView.self){
if子视图点(内部:locationInView,带:nil){
//这一观点包含了这一点
打印(“点击\(Subview.tag)处的子视图”);
打破
}
}
}
}
}

那么,
tapCard
函数调用了吗?顺便说一句,您尚未对任何内容使用
cardNumber
属性。请更正@DávidPásztor:“tapCard”函数未被调用(即,当我点击IB上的任何PlayingCardView时,控制台上不会打印任何内容。关于“cardNumber”,您也是正确的,尚未使用,但打算稍后使用。您无法确保函数不是仅由未执行的
print
语句调用的,因为您将其嵌套在
if
语句中:)您应该使用调试器检查函数是否实际被调用(或者在
if
语句之外放置一个print语句),但该
if
语句似乎无论如何都是不必要的。删除了if语句,只在函数中保留了打印。仍然没有打印到控制台。当前情况下的点击将被添加到最后一个视图onlyTanks@sh_khan。我将尽快通过点击手势调用“tapCard”函数。谢谢s@sh_khan。这似乎确实有效……在这里进行测试,并将很快确认。另外,快速旁白:在哪里进行for循环以创建点击手势是最好的:在viewDidLoad(如上所述)中还是在cardView声明中的didSet中?这会有区别吗?一个更合适吗?(很快回复以确认我是否能够按照您的解决方案进行修复)这两种情况都可以,但我建议
viewDidLoad
经过测试,并且似乎有效,@shu khan。谢谢!谢谢,我会看一看。另外,还测试了@shu khan的解决方案,并且似乎有效。感谢替代解决方案,@ankur。
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;
                }
            }

        }

    }

}