BostonMacOSX BostonMacOSX - 2 months ago 11
Swift Question

Looping UITapGestureRecognizer only added to last one not all of them

So I'm up to the point that I'm creating UIViews programmatically based on the amount of an array which is returned from JSON. Everything seems to be going ok except for the loop which is supposed to add the tap to each of the views but it is only adding it to one view. Only prints on the last UIView.

func addsubviews(howmany: Int) -> Void{
let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))

for x in 1...howmany{

guard let v = UINib(nibName: "DealsView", bundle: nil).instantiate(withOwner: nil, options: nil)[0] as? UIView else { return }

v.translatesAutoresizingMaskIntoConstraints = false
guard let lbl = v.viewWithTag(99) as? UILabel else { return }
lbl.text = "Here is a new Label for Loop: " + "\(x)"

self.allContainer.addSubview(v)

v.backgroundColor = UIColor.white

var horizontalConstratint1 = NSLayoutConstraint()
var horizontalConstratint2 = NSLayoutConstraint()
var verticalConstraint1 = NSLayoutConstraint()

heightConstraint = v.heightAnchor.constraint(equalToConstant: 100)
horizontalConstratint1 = v.leadingAnchor.constraint(equalTo: (v.superview?.leadingAnchor)!, constant: 10)
horizontalConstratint2 = v.trailingAnchor.constraint(equalTo: (v.superview?.trailingAnchor)!, constant: -10)

if prevView == nil{
verticalConstraint1 = v.topAnchor.constraint(equalTo: (v.superview?.topAnchor)!, constant: 20)
}else
{
if let pv = prevView as? UIView {
verticalConstraint1 = v.topAnchor.constraint(equalTo: (pv.bottomAnchor), constant: 20)
}
}
NSLayoutConstraint.activate([horizontalConstratint1,horizontalConstratint2,verticalConstraint1])

prevView = v
}

if let pv = prevView as? UIView {
print("final constratint")
NSLayoutConstraint.activate([
self.allContainer.bottomAnchor.constraint(equalTo: pv.bottomAnchor, constant: 20)
])
}

for views in self.allContainer.subviews{
print("adding views")
views.addGestureRecognizer(tap)
}

}

Answer

You have just a single UITapGestureRecognizer before your view loop starts. AFAIK, tap gesture recognizers can only be attached to one view at a time. Check out this question. To solve this, try writing this line:

let tap = UITapGestureRecognizer(target: self, action: Selector("handleTap"))

inside your view loop.


To find out what view was tapped, make your selector handleTap take an argument like so:

Selector("handleTap:")

and the method itself like this:

func handleTap(sender: UITapGestureRecognizer? = nil) {
    // You can get the view here by writing
    let v = sender.view
}