iosswiftxcodeuitableviewtouches

SWIFT: touchesEnded not being called when I touch the screen


So I have a tableviewController called SettingsViewController, and it has the following touchesEnded function:

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    print("A")

    super.touchesEnded(touches, with: event)
    print("B")
    
    if let touch = touches.first {
        print("C")
        let touchLocation = touch.location(in: view)

        // 290 because the width of the view is 414, and the SettingsViewController width gets set to 0.7 * the view width in SlideInTransition.  0.7 * 414 is 289.8
        if touchLocation.x > 290 {
            dismiss(animated: true)
        }
    }
}

I made the print statement to see if it was being called, which it is not. This view controller is presented with a 'menu-esque' slide in custom transition. Is it possible that the bounds of the UIView of the new tablevc displayed with a custom transition is the problem somehow? Regardless, I have tried implementing super.touchesEnded, or adding all the override touches functions and tapped all over the screen with each simulation, but the touchesEnded never gets called. Any idea what's wrong and how to fix it? Thanks


Solution

  • I'm going to guess that you're putting the touchesEnded() func in your table view controller ... which is not going to work. The table view itself is consuming the touches.

    This might work for you...

    Add this UITableView subclass to your project:

    class TouchableTableView: UITableView {
        
        var callback: (() -> ())?
        
        override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
            print("A")
            
            super.touchesEnded(touches, with: event)
            print("B")
            
            if let touch = touches.first {
                print("C")
                let touchLocation = touch.location(in: self)
                
                // not clear where you're trying to check for touch, so this may need to be changed
                
                // 290 because the width of the view is 414, and the SettingsViewController width gets set to 0.7 * the view width in SlideInTransition.  0.7 * 414 is 289.8
                if touchLocation.x > 290 {
                    // this code is in a UITableView subclass,
                    //  so we can't call dismiss() from here
                    //dismiss(animated: true)
    
                    // instead, we tell the Controller to take action
                    callback?()
                }
            }
        }
    
    }
    

    Then, in Storyboard, select the Table View in your Table View Controller and assign its Custom Class to TouchableTableView:

    enter image description here

    enter image description here

    enter image description here

    Now, touchesEnded() will be called in the custom TouchableTableView class (unless you tap on an interactive UI element in the cell, such as a button).

    We then use the "callback" closure to tell the Controller about the touch. So, in your UITableViewController, add this in viewDidLoad():

    class ExampleTableViewController: UITableViewController {
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            // we're in a UITableViewController,
            // so make sure the tableView is our TouchableTableView class
            // if it is, setup the closure
            if let tv = tableView as? TouchableTableView {
                tv.callback = {
                    // here is where we would, for example, call dismiss()
                    self.dismiss(animated: true, completion: nil)
                }
            }
    
        }
    
    }