[UITapGestureRecognizer] UILabel을 클릭가능하도록 만들기

2021. 12. 17. 13:06UIKit, SwiftUI, H.I.G

원래 액션 이벤트를 담당하는 UI 요소는 "버튼"이다.

하지만 iOS 개발을 하다 보면, 경우에 따라 일반 뷰에나 이미지 뷰, 라벨에도 버튼을 구현해야 할 때가 생기게 된다.

오늘은 이럴 경우에, 버튼이 아닌 요소에도 Action을 어떻게 표현할 수 있는지 알아보려 한다.
(코드에서는 UILabel을 예시로 들지만, 요소를 다른 걸로 바꿔주기만 하면 모두 응용해서 사용 가능하다.)

전체적인 기능 구현에 대한 프로세스는 아래와 같다.

1️⃣ Action을 주고 싶은 요소에 대해 Outlet을 만든다.
2️⃣ UITapGestureRecognizer를 이용해 클릭을 인식할 수 있도록 만든다.
3️⃣ 클릭했을 때, 구현할 코드를 함수에 작성한다.
4️⃣ isUserInteractionEnabled를 true로 바꿔준다.

 

1️⃣ Action을 주고 싶은 요소에 대해 Outlet을 만든다.


일단 이 코드에서는 UILabel을 예시로 만들어줄 거기 때문에, 해당 UILabel에 대해 IBOutlet 변수로 연결을 해두었다.

    // MARK: - @IBOutlet Properties
    @IBOutlet weak var titleLabel: UILabel!

 

2️⃣ UITapGestureRecognizer를 이용해 클릭을 인식할 수 있도록 만든다.


UITabGestureRecognizer는 viewDidLoad()와 같은 생명주기에 바로 넣어줘도 되지만,
나 같은 경우에는 함수로 따로 빼서, 생명주기에서는 호출을 하도록만 넣어주는 편이다.

아무튼, 해당 요소를 클릭했을 때, 클릭했다는 것 자체를 알아채기 위해 사용자의 탭을 인식하는 UITabGestureRecognizer를 UILabel에 추가해주었다.

private func setupGestureRecognizer() {
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(labelClicked))
    titleLabel.addGestureRecognizer(tapGestureRecognizer)
}

 

3️⃣ 클릭했을 때, 구현할 코드를 함수에 작성한다.


아까 UITapGestureRecognizer에 action으로 연결해둔 #selector의 자세한 구현을 해줄 차례이다.

@objc private func labelClicked(_ tapRecognizer: UITapGestureRecognizer) {
    // 라벨을 클릭했을 때, 구현할 기능 추가 (화면전환이나 데이터 전달 등..)
}

 

4️⃣ isUserInteractionEnabled를 true로 바꿔준다.


보통, 이렇게까지만 추가를 해주면 잘 기능이 작동할 줄 알았는데,,, 잘 되지 않았다.

어떤 문제인고 찾아봤더니 코드 하나를 확인해줄 필요가 있었다.

 

isUserInteractionEnabled유저의 이벤트가 event queue로부터 무시되고 삭제됐는지 판단하는 Boolean 값이다.

만약 false로 set 하면, view를 위한 touch, press, keyboard 그리고 focus event는 event queue에서 무시되고 삭제된다.
true로 set하면 event는 정상적으로 view에게 전달되는데, default value는 true이다.

titleLabel.isUserInteractionEnabled = true

 

⭐️전체 코드⭐️


class ExampleViewController: UIViewController {

    // MARK: - @IBOutlet Properties
    @IBOutlet weak var titleLabel: UILabel!

        // MARK: - View Life Cycle
        override func viewDidLoad() {
      	    super.viewDidLoad()

            setupGestureRecognizer()
        }
	
// MARK: - Extensions
extension ExampleViewController {
    
    private func setupGestureRecognizer() {
        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(labelClicked))
        titleLabel.addGestureRecognizer(tapGestureRecognizer)
        titleLabel.isUserInteractionEnabled = true
    }
    
    @objc private func labelClicked(_ tapRecognizer: UITapGestureRecognizer) {
        let nextVC = GroupNameEditBottomSheetViewController()
                    .setTitle("그룹명 변경")
                    .setHeight(184)
        nextVC.modalPresentationStyle = .overFullScreen
        self.present(nextVC, animated: false, completion: nil)
    }
    
}