오늘은 프로젝트 도중에 탭제스처를 사용하다가 발생한 문제에 대해서 써보겠습니다.
UIGestureRecognizer을 상속 받은 class이다.
single 혹은 multi tap을 해석하는 제스처를 인식하는 class라고 한다.
UIButton은 UIControl을 상속받으므로 별도 처리하지 않아도 이벤트를 인식한다.
하지만 ImageView나 View는 UIControl을 상속받지 않으므로 별도의 처리를 통해 이벤트를 감지하고 생성하게 만들어야한다.
저의 경우에는 하단의 footerView를 하나 생성해서 view가 눌렸을 때 이벤트를 처리하려고 했습니다. 그래서 하나의 view를 만들고 그 view에 tapGestureRecognizer이라는 메서드를 사용했다.
제스처를 인식할 target과 인식했을 경우 어떤 이벤트를 처리할지 #selector에 지정해주면 된다.
#selector
는 Objective-C에서 사용되는 메서드를 참조할 때 사용되는 swift문법이고, @objc
는 swift 메서드나 속성을 Objective-C 런타임에서도 사용할 수 있도록 표시하는 키워드이다.인식하는 기준은 frame의 크기
이다. 여기까지 잘 연결이 되어있는걸 확인했지만 막상 하단의 footerView를 눌렀을 때 미리 적어놓은 print문이 실행이 되지 않는 것을 발견했다. 그리고 footerView가 있음에도 View뒤에 collection뷰가 터치가 되어 움직이는 모습도 발견했다.
오른쪽부터 4번째에 있는 아이콘은 Debug view Hierarchy기능을 사용할 수 있다. 이 기능은 현재 View의 상태를 확인할 수 있고 어떤식으로 컴포넌트들이 쌓여 있는지 확인을 할 수 있다.
위의 사진과 같이 뷰의 계층을 보여준다. 스토리보드에서 작업했을때 볼 수 있는 계층도이며, view의 오른쪽에 보면 보라색으로 경고창이 떠있는걸 볼 수 있다. 이 의미는 현재 View의 레이아웃이 제대로 이루어지지 않았다는걸 알려주는 경고창이다.
위의 사진은 제가 마주친 문제의 부분이다. 첫번째 사진처럼 눈으로 보기에는 이상함을 느끼지 못했다. 하지만 옆모습을 보면 빨강색으로 된 footerView영역 뒤에보면 앱의 최하단까지 collection View가 내려와있는걸 볼 수 있다. 그렇다고해도 앞에 View가 있고 터치를 한다면 작동을 해야한다고 생각되지만 로그창에 print문이 찍히지 않는걸 알 수 있었다.
첫번째 시도
footerView위에 두개의 label이 올라와 있고 두개의 label들 또한 UIConrol을 상속받지 않기때문에 이벤트가 발생하지 않는다. 그리고 UIView를 상속받는 클래스들은 isUserInteractionEnabled
라는 항목이 false
로 설정되어 있다(UIView는 true로 활성화가 되어있음). 이는 사용자의 상호작용이 활성화가 되어있지 않다는걸 의미한다. 그래서 tapGesture를 인식하지 못하게 되는 상황이 발생한다.
isUserInteractionEnabled
라는 항목이 true
로 설정두번째 시도
위에 문제점을 발견한 collectionView와 footerView의 위치에 대한 의문이 있었다. 그래서 아까 지나간 보라색 경고창을 다시 확인해보았다.
height와 vertical의 제약조건이 애매하다고 나왔다. 그래서 자세히 보니 현재 footerView의 height를 보면 0이라는 걸 확인할 수 있었다.
Auto Layout을 잡기 위해서는 위치와 크기가 필수이다. height을 50을 줬더라도, 뷰의 상단과 하단 사이를 명확히 정의하지 않으면 Auto Layout은 뷰를 배치할 수 없다고 판단할 수 있었다. 그래서 제대로된 top과 bottom에 제약조건을 다시 설정해주었다.
이렇게 스토리보드 없이 작업을 하다보니 오토레이아웃을 잡아가는 과정에서 헷갈리고 어려움이 있었다. 하나씩 크기와 위치를 생각하며 작업을 한다면 실수를 줄일 수 있을거 같다. 이번 트러블슈팅으로 인해 탭제스처의 인식 범위에 대해서도 알게된 계기가 되었다.
눈물의 프로젝트.. 고생했어여ㅠ