I have a UIScrollView
which has a UIView
as a subview, which in return holds all my FooView
s, which is a UIView
as well. Each of those FooView
s has a gesture recognizer. The gestures are being detected just fine for the first FooView
in my scroll view (meaning, the selector is being triggered correctly), but all subsequent FooView
s do not trigger that gesture.
This question's answer Subview Gesture Recognizer not being called I assume explains the problem that I am facing. Quoting: "[...] the issue was that the subview with gesture recognizer was outside the frame of the superview. This means even though the view was being drawn, the gestures were not detected".
I understand the problem at hand, but am not sure how to solve it.
Btw: It works perfectly, if I add the FooView
s directly to the scroll view, instead of adding them to contentView
. However, for my use case that is not an option, because I am using auto-layout and the constraints would be messed up otherwise.
Attached you'll find my MWE where you can see that tapping on the first view will print out "Tapped", but there will be no output for the other views. The code is just a playground example, so can be copied there to run.
import UIKit
import PlaygroundSupport
class AwesomeView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.getRandomColor()
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(tapHandler))
self.addGestureRecognizer(tapGesture)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
guard let superview = superview else {
return
}
self.frame = superview.frame
}
func tapHandler(_ sender: AnyObject) {
print("Tapped")
}
}
extension UIColor {
static func getRandomColor(_ hash: UInt32 = arc4random()) -> UIColor{
let randomRed:CGFloat = CGFloat(hash) / CGFloat(UInt32.max)
let randomGreen:CGFloat = CGFloat(hash << 4) / CGFloat(UInt32.max)
let randomBlue:CGFloat = CGFloat(hash << 2) / CGFloat(UInt32.max)
return UIColor(red: randomRed, green: randomGreen, blue: randomBlue, alpha: 1.0)
}
}
class DummyVC: UIViewController, UIScrollViewDelegate {
let scrollView = UIScrollView(frame: CGRect(x:0, y:0, width:320,height: 300))
var contentView: UIView!
var frame: CGRect = CGRect(x:0, y:0, width:0, height:0)
override func viewDidLoad() {
super.viewDidLoad()
contentView = UIView(frame: scrollView.frame)
scrollView.addSubview(contentView)
self.view.addSubview(scrollView)
for index in 0..<4 {
frame.origin.x = self.scrollView.frame.size.width * CGFloat(index)
frame.size = self.scrollView.frame.size
self.scrollView.isPagingEnabled = true
let subView = AwesomeView(frame: frame)
self.contentView.addSubview(subView)
}
self.scrollView.contentSize = CGSize(width:self.scrollView.frame.size.width * 4, height: self.scrollView.frame.size.height)
}
}
PlaygroundPage.current.liveView = DummyVC().view
PlaygroundPage.current.needsIndefiniteExecution = true