touchesBegan vs TapGestureRecognizer

이원희·2020년 12월 15일
2

📱 iOS

목록 보기
8/24
post-thumbnail

오늘은 touchesBeganTapGestureRecognizer에 대해 알아볼거다.

포스팅 계기는 다음과 같다.
프로젝트를 진행하면서 UITextField가 아닌 곳을 터치하면 키보드가 내려가도록 구현해야 했다.
처음에는 아래와 같은 코드로 구현했고, 잘 동작하였다.

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

여기서 내가 받은 리뷰는 다음과 같다.
(감사합니다. 흰!🤍)

  1. touchesBegan() 은 무슨 역할을 하는 함수인가요?
  2. method 를 override 했는데 super 를 호출하지 않는 이유가 있나요?
  3. UITapGestureRecognizer를 사용해보면 어떨까요? 그리고 touchesBegan() 과는 어떤 차이가 있을까요?

오늘은 위의 리뷰들에 대한 답변들을 찾아가는 흐름으로 포스팅을 진행해보자.

1. touchesBegan()은 무슨 역할을 하는 함수인가요?

touchesBegan()이란 무엇일까?
우선 내가 위와 같은 코드를 사용했던 이유는 구글링하니 나오는 코드였고, 실제로 잘 동작했기 때문이다.
(이러면 안되는데.... 지금은 안 그러도록 습관?을 바꾸는 중이다.)

공식 문서에서 touchesBegan()을 찾아보자!

touchesBegan()view나 window에서 터치가 발생하면 불리는 함수라고 한다.

위와 같은 코드를 작성하면 화면을 터치할 때마다 로그가 찍히는 것을 확인할 수 있다.

touchesBegan()과 관련된 다른 함수들은 뭐가 있을까?

공식 문서를 쭉 보다보면 위와 같은 함수들을 소개해준다.
대충 이름들이 touches로 시작하는 것을 보니 친구들인가보다!

우선 공식 문서의 설명대로 써본다면!

touchesBegan

터치가 시작될 때 불려지는 함수

touchesMoved

터치 이벤트가 바뀔 때 불려지는 함수

touchesEnded

손가락이 view나 window에서 떨어질 때 불려지는 함수

touchesCancelled

alert과 같이 시스템 이벤트로 터치의 흐름이 취소될 때 불려지는 함수

(한 번 코드로 확인해보자!)

위의 코드와 로그를 통해 다음과 같은 사실을 알 수 있다.

  • 사용자의 손가락이 화면에 닿는 순간에 touchesBegan이 호출된다.
  • 화면을 터치한 상태에서 손가락을 움직이면 touchesMoved가 계속 호출된다.
  • 사용자의 손가락이 화면에서 떨어지는 순간에 touchesEnded가 호출된다.

(늘 생각하지만 기본 함수들은 이름만 봐도 어떨때 호출되는지 어떤 역할을 하는지 알수 있는거 같다. 나도 이렇게 네이밍할 수 있도록 노력해야지)

이번에는 touchesCancelled를 한 번 찍어보자

위와 같이 화면에 터치한 상태에서 홈 화면으로 빠져나온다면 어떻게 될까?

touchesEnded가 아닌 touchesCancelled가 로그에 찍혔다.
위에서 touchesCancelled는 alert과 같이 시스템 이벤트로 터치의 흐름이 취소될 때 불려지는 함수라고 했다.
위의 사진은 사용자가 화면에 손가락을 터치한 채로 홈화면으로 빠져나가는 것이니 터치의 흐름이 취소된다고 볼 수 있다.

그렇다면 이제 리뷰에 대해 답변해보자!

Q. touchesBegan()은 무슨 역할을 하는 함수인가요?

A. 화면에 사용자의 손가락이 닿기 시작할때 호출되는 함수로 사용자가 화면 터치를 시작했음을 알리는 역할을 합니다.

2. method를 override 했는데 super를 호출하지 않는 이유가 있나요?

override한 method지만 super를 호출하지 않았던 이유는 구글링했던 코드가 우선 그렇게 나와있었고;;
그렇게 작성한 코드가 잘 동작했기 때문이다....;;
다시 한 번 말하지만 이러면 진짜 안된다...ㅋㅋㅋㅋㅋ나부터 고치자...
(사실 이 질문의 답변을 찾기 위해 정말 많이 고민했고, 많이 헤맸다! 이와 관련해서 아직 모르는 부분이 나올 수 있지만 그것도 조만간 다뤄봐야겠다!)

위의 사진은 touchesBegan()의 Discussion이다.
Discussion에 뭐라고 써있는지 하나씩 확인해보자.

  • view나 window에서 새로운 터치가 감지될때 UIKit에서 이 method를 호출한다.
  • 많은 UIKit 클래스들은 이 method를 override하고 touch event들을 핸들링할때 사용한다.
  • 이 method는 기본적으로 responder chain을 통해 message(event)를 전달한다.
  • 이 method를 가진 subclass들을 만들때에는 너가 직접 event들을 핸들링할 것이 아니라면 모든 event들을 전달하기 위해서는 super를 호출해줘야 한다.
  • 만약 이 method를 super 호출 없이 override한다면 반드시 touch event들을 핸들링하는 다른 method들에서 하는 일이 없더라도 override 해줘야한다.

위의 Discussion들을 읽다 보면 Responder Chain을 통해 message(event)를 전달한다고 한다.
(Responder Chain은 이후 포스팅에서 다뤄보겠다!)

Responder는 이벤트를 핸들링하고 event에 반응할 수 있는 객체이다.
event가 발생하면 UIKit는 event 핸들링을 위해 해당 event를 앱의 Responder 객체들에게 보낸다.
Responder 객체들은 처리되지 않은 event를 App의 다른 파트로 forwarding하기도 한다.
이때 Responder ChainResponder 객체들이 event나 message를 핸들링하도록 다른 객체들에게 전송할 수 있도록 해준다.
즉, 특정 Responder가 event를 핸들링하지 않을 경우 해당 Responder는 event를 Responder Chain의 다음 Responder 객체로 forwarding한다.

위에서 살펴본 바로는 super가 Responder Chain과 관련이 있는거 같다.
Responder Chain은 event를 전달해주는데 관련이 있는거 같다.
그렇다면 우리는 2개의 화면을 이용해서 touch event가 어떻게 전달되는지 확인해보자.

두번째 화면으로 이동! 버튼을 클릭하면 두번째 화면으로 이동하도록 구성했다.

super를 호출하지 않으면 어떻게 될까?

위와 같이 첫번째 VC와 두번째 VC를 구성했고 아래와 같이 action을 했다.

이렇게만 보면 뭐가 다른지 모르겠으니 일단 이렇게 나온다는 것을 알아두고 다음 step으로 넘어가보자.

super를 호출하면 어떻게 될까?

이번에는 super를 호출해보고 위의 로그와 어떻게 다른지 확인해보자.

첫번째 화면 touch까지는 위의 로그와 동일하게 찍히는 것을 확인할 수 있다.
두번째 화면 touch는 위의 로그와 다르게 찍힌다!

super를 호출하지 않은 코드에서는 두번째 화면을 touch해도 첫번째 화면의 touch method가 호출되지 않았다.
super를 호출하는 코드에서는 두번째 화면을 touch하면 첫번째 화면의 touch method도 호출되는 것을 볼 수 있다.

super를 호출해야하는 이유는?!

우리는 이제 super를 호출하면 Responder Chain을 통해 event가 전달되는 것을 알게되었다.
그렇다면 Discussion에서 직접 event들을 핸들링할 것이 아니라면 event들을 전달하기 위해서는 super를 호출하라는 이유도 Responder Chain 때문임을 알 수 있다.

3-1. UITapGestureRecognizer를 사용해보면 어떨까요?

UITapGestureRecognizer를 사용하기 전에 이게 무엇인지 먼저 알아보자.

single 혹은 multi tap을 해석?하는 제스처 인식 class라고 한다.
UITapGestureRecognizerUIGestureRecognizer를 상속받고 있다.
UIGestureRecognizer는 view 위에서 발생하는 패턴이 존재하는 event들을 처리한다.
여기서는 Tap이라는 패턴의 event를 처리하는 gestureRecognizer이다.

Tap 이외의 gestureRecognizer의 종류는 위와 같다.
UITapGestureRecognizer에 대해서는 다음 포스팅에서 좀 더 다뤄보겠다.

3-2. 그리고 touchesBegan() 과는 어떤 차이가 있을까요?

touchesBegan()UITapGestureRecognizer와의 차이는 다음과 같다.

  • touchesBegan()은 사용자의 손가락을 화면에 닿을때마다 호출된다.
  • UITapGestureRecognizer는 Tap일 경우에만 호출된다.
  • 즉, pinch를 하려고 화면을 터치해도 touchesBegan()이 호출된다는 것이다.

GestureRecognizer는 해당 gesture인지 아닌지 판별하는데 시간이 걸린다.

마무리

리뷰를 받고 touchesBegan()UITapGestureRecognizer에 대해 알아봤다.
그리고 GestureRecognizer를 사용하는게 더 맞다고 판단해서 코드를 변경하였다.
코드 변경 이유는 사용자가 keyboard를 내리는 방법은 tap이 맞다고 생각해서이다.

0개의 댓글