Post

UIKit - UIScrollView touchesBegan 메서드가 호출되지 않는 문제 해결하기

UIKit - UIScrollView touchesBegan 메서드가 호출되지 않는 문제 해결하기

UIScrollView를 적용하여 View를 구성하였고, ViewController에서 touchesBegan 메서드를 오버라이딩하여 화면을 터치했을 때 키보드가 내려가도록 처리하였음.

touchesBegan 구현 내용

1
2
3
4
5
6
7
8
9
10
11
12
13
import UIKit

final class RegisterViewController: UIViewController {

    ...

    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        self.view.endEditing(true)
    }

    ...

}

하지만 아래 사진처럼 키보드가 올라온 상황에서 아무 화면이나 터치했을 때 touchesBegan이 제대로 실행되지 않고있음.

image

이 동작의 원인은 UIScrollView가 터치 이벤트를 스크롤 동작으로 더 먼저 처리하기 때문임.

이를 해결하기 위해선 UITapGestureRecognizer를 통해서 제스처를 처리해줘야함.

RegisterView.swift

1
2
3
4
5
6
7
8
9
10
11
import UIKit
import SnapKit

final class RegisterView: UIView {

    func setupTapGesture(tapGesture: UITapGestureRecognizer){

        // UITapGestureRecognizer를 scrollView에 설정
        scrollView.addGestureRecognizer(tapGesture)
    }
}

RegisterViewController.swift

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import UIKit

final class RegisterViewController: UIViewController {
    
    private let registerView = RegisterView()
    
    override func loadView() {
        
        ...

        // UITapGestureRecognizer 인스턴스 생성 
        let gesture = UITapGestureRecognizer(target: self, action: #selector(tapGesture))

        // UITapGestureRecognizer가 터치 이벤트를 처리한 후 다른 view에도 전파되도록 설정
        gesture.cancelsTouchesInView = false

        // scrollView에 제스처 적용
        registerView.setupTapGesture(tapGesture: gesture)
        
        self.view = registerView
    }
    
    @objc private func tapGesture(){

        // 키보드 내리기
        view.endEditing(true)
    }

    ...
}

cancelsTouchesInView 프로퍼티는 UITapGestureRecognizer가 터치를 인식한 후 해당 터치 이벤트를 하위 view에 전달하지 않고 취소할지 여부를 결정함.

cancelsTouchesInView 프로퍼티의 기본값은 true 이며, 이 경우엔 제스처가 인식되면 하위 view의 터치 이벤트(touchesBegan, touchUpInside 등)는 취소되어 전달되지 않게됨.

결과

image

Reference

This post is licensed under CC BY 4.0 by the author.