1

I would like to add taps to views which subclasses another view, but my current approach does not get invoked, ie the seatNumber does not get printed when my seats are tapped as coded in the handleTap function. I have adapted my approach from the following this post and this. My code thus far:

//My viewController
class ViewController: UIViewController, UIScrollViewDelegate {
    let scrollView = UIScrollView()
    let cinema: CinemaView = {
        let v = CinemaView()
        return v
    }()

    override func viewDidLoad() {
        super.viewDidLoad()

        let seat1 = SeatView()
        seat1.isVacant = false
        seat1.seatNumber = "2A"

        let seat2 = SeatView()
        seat2.isVacant = true
        seat2.seatNumber = "3B"

        cinema.seats = [seat1, seat2]

        let tap = UITapGestureRecognizer(target: seat1, action: #selector(handleTap))
        seat1.addGestureRecognizer(tap)
        seat1.isUserInteractionEnabled = true

        view.addSubview(scrollView)
        scrollView.addSubview(cinema)

    }

    @objc func handleTap(_ seat: SeatView) {
        if let seatNumber = seat.seatNumber {
            print("\(seatNumber) is tapped")
        } else {
            print("Seat tapped")
        }
    }

//My custom cinemaView
class CinemaView: UIView {

    var seats = [SeatView]() {
        didSet {
            for v in self.subviews {
                v.removeFromSuperview()
            }
            var seatRect = CGRect(x: 0, y: 0, width: 20, height: 20)
            for seat in seats {
                self.addSubview(seat)
                seat.frame = seatRect
                seatRect.origin.x += seatRect.size.width + 8
             }
        }
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

//My Custom seatView
class SeatView: UIView {

    var isVacant: Bool = true 
    var seatNumber: String?

    override init(frame: CGRect) {
        super.init(frame: frame)    
    }
}

Note: some boilerplate codes have been omitted above to keep the code concise for this question.

My preferred approach is to add these taps inside the VC so that I can pass this info into another VC and push up to Firebase. Any advice would be much appreciated

EDIT: Added screenshot of UI

enter image description here

Koh
  • 2,687
  • 1
  • 22
  • 62
  • Try using this: `self` instead of `seat1` in this statement `UITapGestureRecognizer(target: seat1, action: #selector(handleTap))` and – 3stud1ant3 Oct 14 '17 at 05:44
  • @3stud1ant3 tried, doesn't work either. – Koh Oct 14 '17 at 05:45
  • Can you show the screenshot of UI, are seat views being show on the screen correctly? – 3stud1ant3 Oct 14 '17 at 06:18
  • I think the problem is in adding `seat1` and `seat2` in `cinema` view, and since I think this is not the actual code you are running so it is difficult to point out the problem and I also think the frames are not set properly – 3stud1ant3 Oct 14 '17 at 06:25
  • @3stud1ant3 I have added the full code for cinemaView and the screenshot of the UI. So far the seatViews are shown correctly. Other codes are just constraints. – Koh Oct 14 '17 at 07:11
  • Is your problem solved? – 3stud1ant3 Oct 14 '17 at 14:26
  • @3stud1ant3 no it isn't – Koh Oct 14 '17 at 14:30

1 Answers1

0

With the help of 3stud1ant3, I managed to figure out where went wrong.

After observing the view layout, the cinemaView was never added to the view even though the seatViews were added. By defining more constraints to cinemaView in viewDidLoad at the viewController and incorporating 3stud1ant3's code in the below answer post, the tap functions worked.

override func viewDidLoad() {
    super.viewDidLoad()

    view.backgroundColor = .blue

    cinema.seats = [seatView1, seatView2]

    view.addSubview(scrollView)
    scrollView.addSubview(cinema)

    let views = ["scrollView": scrollView, "v": cinema] as [String : Any]
    let screenHeight = view.frame.height

    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[scrollView(\(screenHeight / 2))]", options: NSLayoutFormatOptions(), metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[scrollView]|", options: NSLayoutFormatOptions(), metrics: nil, views: views))
    view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-60-[v(50)]", options: NSLayoutFormatOptions(), metrics: nil, views: views))

    //Previously, the below constraints were not added. Once these are added, the tap function works
    cinema.leftAnchor.constraint(equalTo: scrollView.leftAnchor).isActive = true
    cinema.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    cinema.widthAnchor.constraint(equalTo: scrollView.widthAnchor ,constant: 100).isActive = true

}
Koh
  • 2,687
  • 1
  • 22
  • 62