0
votes
  1. I have a MasterController: UIViewController
  2. Inside is a UIView(mainViewContainer) -> self.frame
  3. mainViewContainer contains MainViewController: UIViewController
  4. MainViewController has a mainCollectionView: UICollectionView .horizontal with 3 cells
  5. mainCollectionView cells have a UITableView inside it

I have added a UITapGestureRecognizer to the MasterController's view to perform an action in the UITableView.

It works fine in the first CollectionViewCell but when i scroll to the next cell the tap gesture responds only after 3 taps, but i want it to respond on first tap like it does in the first cell.

Note: after the the 3 taps it starts working normal on single taps. this only happens when the app is initialized after build.

This is in my tableViewCell:

class CustomTableViewCell: UITableViewCell {

  let customView: UIView = {
     let view = UIView()
     view.backgroundColor = .white
     view.translatesAutoresizingMaskIntoConstraints = false
     return view
  }()

  let moreButton: UIButton = {
        let button = UIButton(type: .system)
        button.setImage(#imageLiteral(resourceName: "moreButton").withRenderingMode(.alwaysOriginal), for: .normal)
        button.contentMode = .scaleAspectFit
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()

  lazy var tapGesture: UITapGestureRecognizer = {
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(_:)))
        tapGesture.cancelsTouchesInView = false
        return tapGesture
    }()

  var master = UIApplication.shared.keyWindow?.rootViewController as? MasterViewController

  var isCustomViewOpen = false

  override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        setupCustomView()
        setupMoreButton()

        master?.view.addGestureRecognizer(tapGesture)
  }

  func setupCustomView() {
        customView.layer.cornerRadius = 7
        addSubview(customView)
        NSLayoutConstraint.activate([
            customView.topAnchor.constraint(equalTo: topAnchor, constant: 10),
            customView.leftAnchor.constraint(equalTo: leftAnchor, constant: 10),
            customView.rightAnchor.constraint(equalTo: rightAnchor, constant: -10),
            customView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -10),
            ])
    }

    func setupMoreButton() {
        customView.addSubview(moreButton)
        moreButton.addTarget(self, action: #selector(handleMoreButton(_:)), for: .touchDown)
        NSLayoutConstraint.activate([
            moreButton.heightAnchor.constraint(equalToConstant: 15),
            moreButton.widthAnchor.constraint(equalToConstant: 20),
            moreButton.centerYAnchor.constraint(equalTo: customView.centerYAnchor),
            moreButton.trailingAnchor.constraint(equalTo: customView.trailingAnchor, constant: -20)
            ])
    }

    @objc func handleMoreButton(_ sender: UIButton) {
        isCustomViewOpen ? slideCustomViewRight() : slideCustomViewLeft()
    }

    func performAnimations(transform: CGAffineTransform) {
        UIView.animate(withDuration: 0.3, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
            self.customView.transform = transform
        })
    }

    func slideCustomViewLeft() {
        isCustomViewOpen = true
        performAnimations(transform: CGAffineTransform(translationX: -self.frame.width/3.2, y: 0))
        tapGesture.isEnabled = true
    }

    func slideCustomViewRight() {
        isCustomViewOpen = false
        performAnimations(transform: .identity)
        tapGesture.isEnabled = false
    }

    @objc func handleTapGesture(_ sender: UITapGestureRecognizer) {
        slideCustomViewRight()
    }

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


}
1
the tap gesture(s) is conflicting with the collection views own gestures. you can configure them to work together but that can cause other issues. what exactly does your tap gesture do? or what is it needed for? - Scriptable
@Scriptable the tableview rows are a custom uiview which displays tasks. i have added a button to slide this custom view to the left and show another view with a trash button. So the tap gesture anywhere else closes this custom view. - khalilAli
Try func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) or touchesEnded and check tapped location, if outside your view - close custom view - canister_exister

1 Answers

0
votes

I had tried shouldRecognizeSimultaneouslyWith otherGestureRecognizer: before but i guess i was doing something wrong somewhere.

thanks to @Scriptable in comments i tried again and works now. We should always go back and try again if nothing works.

solved by following way:

first added delegate function to MasterViewController ->

extension MasterViewController: UIGestureRecognizerDelegate {

    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return true
    }
}

And then added delegate to tap gesture ->

var master = UIApplication.shared.keyWindow?.rootViewController as? MasterViewController

tapGesture.delegate = master