카테고리 없음

[Swift - UIKit] tableView 또는 scrollView 에서 터치 이벤트가 안될때

분홍이귀여워 2024. 11. 2. 21:36
반응형

앱을 만들 때 키보드를 사용 후 키보드를 제외한 빈 곳을 터치했을 때 키보드를 내려가게 하려면 touchesBegan(_:with:) 메서드를 이용한다. 하지만 tableView 또는 scrollView 에서는 touchesBegan(_:with:) 메서드가 안먹힌다.
그 이유는  tableView 또는 scrollView는 스크롤 기능이 있기 때문에 스크롤을 하려면 일단 한 번의 터치를 하게 되기 때문이다. 
이 문제를 해결하기 위해서는
UITapGestureRecognizer 를 이용해 제스처를 인식하도록 해야한다.

 

 override func viewDidLoad() {
        super.viewDidLoad()
        
        //탭 핸들러 추가
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:)))
        view.addGestureRecognizer(tapGesture)
    }
    
    //터치 발생시 작동하는 함수
    @objc func handleTapGesture(sender: UITapGestureRecognizer) {
    	//이곳에 탭 제스처 했을시 원하는 코드 작성
        handleTap(sender: sender)
    }

 

나의 경우는 빨간색 박스친 부분이 tableView 부분인데 할일을 적는 행 부분과 추가버튼(+버튼) 클릭시에는 제스처를 인식하지 않고 그 두곳을 제외한 나머지 공간을 클릭시에 키보드를 내려가게 하고 싶었다.

 

여러개의 UIViewController 에서 사용하기 위해 프로토콜을 만들고

protocol TapHandling {
    func handleTap(sender: UITapGestureRecognizer)
}

 

탭한 위치가 테이블뷰 또는 버튼일 경우 리턴 처리를 했다.

extension TapHandling where Self: UIViewController {
    func handleTap(sender: UITapGestureRecognizer) {
        if sender.state == .ended {
            // 터치한 뷰가 테이뷰셀 또는 버튼이면 리턴시키고, 나머지는 키보드 내리기
            if let touchView = sender.view?.hitTest(sender.location(in: sender.view), with: nil) {
                if touchView is UITableViewCell || touchView is UIButton { return }
            }
            view.endEditing(true)
        }
        sender.cancelsTouchesInView = false
    }
}

 

그리고 제스처를 인식하고싶은 뷰컨트롤러에서 프로토콜을 채택하면 된다

final class yourViewController: UIViewController, TapHandling { //프로토콜 채택

	 override func viewDidLoad() {
        super.viewDidLoad()
        
        //탭 핸들러 추가
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:)))
        view.addGestureRecognizer(tapGesture)
    }
    
    //터치 발생시 작동하는 함수
    @objc func handleTapGesture(sender: UITapGestureRecognizer) {
    	//이곳에 탭 제스처 했을시 원하는 코드 작성
        handleTap(sender: sender)
    }

}
반응형