iOS) KakaoQRcode 클론코딩 - shake motion event(1/2) - UIResponder

2 minute read

내용

  • 카카오톡에서 두번 흔들면 qr 코드 뷰를 띄어주는 기능 클론코딩

두가지 방법에 대해서 알아볼 것이다.

  1. UIResponder 의 motion event 메서드를 재정의해서 사용
  2. CoreMotion Framework 사용

1️⃣ UIResponder 의 motion event 메서드를 재정의해서 사용

시작 전

👏 원리

  • motion capture delegate 에서 shake gesture 를 capture 해서 사용.

👏 UIResponder

이벤트에 응답하고 처리하기 위한 추상 인터페이스입니다.

overall

이벤트가 발생하면 UIKit 은 처리를 위해서 UIResponder 의 인스턴스에게 보내지게 된다.

touch events, motion events, remote-control events, press events 을 비롯한 여러종류의 이벤트가 있다. 특정유형의 이벤트를 처리하기 위해서는 responder 가 해당 메서드를 재정의 해야한다.

예를 들어, 터치 이벤트를 처리하기 위해 응답자는 touchBegan(:with:), touchMoved(:with:), touchEnded(:with:) 및 touchCancelled(:with:) 메소드를 구현합니다.

다음은 모션 이벤트의 경우 재정의할 메서드이다.

motion event

: Tells the receiver that a motion event has begun.

: Tells the receiver that a motion event has ended.

: Tells the receiver that a motion event has been cancelled.

motionBegan(:with:) & motionEnded(:with:)

UIKit은 모션 이벤트가 시작되고 끝날 때만 responder 에게 알립니다. 중간 흔들림은 보고하지 않습니다. 모션 이벤트는 처음에 첫 번째 responder 에게 전달되고 적절하게 responder chain 위로 전달됩니다.

motionCancelled(_:with:)

motion evnet 가 중단될 때 호출된다. 애플리케이션이 비활성화되거나 모션 이벤트를 처리하는 뷰가 window 에서 제거되도록 하는 모든 것이 이에 해당한다.

흔들림이 너무 오래 지속되면 UIKit 이 메서드를 호출할 수 있다. 모든 responder 는 이 메서드를 구현해야한다.

👏 UIEvent.EventSubtype

Apple Developer Documentation

위의 motion event 와 관련된 일반적인 모션은 UIEvent.EventSubtype.motionShake 로 표시되는 흔들림이다.

시작하기

motion event 를 인식해서 화면전환해보자

  • MainViewController.swift

쉐이크를 인식하는 메인 뷰컨트롤러에 해당

import UIKit
import SnapKit

class MainViewController: UIViewController {

    // ...

    // MARK: - View Life Cycle

    override func viewDidLoad() {
        super.viewDidLoad()
        configUI()
        setLayout()

        // ✅ UIKit 이 이 object 를 window 에서 first responder 로 만들도록 한다.
        becomeFirstResponder()
    }
}

// MARK: - Extensions

extension MainViewController {

    private func configUI(){
        // ...
    }

    private func setLayout() {
        // ...
    }

    // ✅ responder 는 자신이 first responder 가 될 수 있게 하기 위해서 canBecomeFirstResponder 프로퍼티를 오버라이드해서 ture 를 리턴하도록 만들어야 한다.
    // ✅ UIView 는 UIResponder 의 상속을 받기 때문에 아래와 같이 재정의할 수 있는 이유가 된다.
    override var canBecomeFirstResponder: Bool {
        return true
    }

    @objc
    private func presentToQRCodeVC() {
        let nextVC = QRCodeViewController()
        nextVC.modalPresentationStyle = .overFullScreen
        present(nextVC, animated: true, completion: nil)
    }

    // ✅ **shake motion detect with UIResponder**
    override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("shake began")
            presentToQRCodeVC()
        }

        // ✅ 조건문을 사용해서 motion 을 비교하지 않고 아래의 코드처럼 사용해도 괜찮다. 일반적으로 사용할 때는 motionShake 에 해당되기 때문이다.
        // print("shake began")
        // presentToQRCodeVC()
    }

    override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("shake ended")
        }
    }

    override func motionCancelled(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("shake cancelled")
        }
    }
}

위의 코드를 통해서 디바이스를 흔들면 올바르게 해당 메서드가 호출되는 것을 확인해볼 수 있다.

❗️motion event 가 두번 연속 발생하면 화면전환해보자

motionEnded(_:with) 메서드를 다음과 같이 수정하면서 구현해보았다.

override func motionEnded(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
        if motion == .motionShake {
            print("shake ended")

            motionNumber += 1
            print("motionNumber: \(motionNumber)")

            if motionNumber == 2 {
                motionNumber = 0
                presentToQRCodeVC()
            }
        }
    }

아쉬운 점

motion 의 횟수에 대한 변수를 설정하고 2번 흔들림이 발생하면 present 하고 싶었는데 위의 motionBegan(_:with:) , motionEnded(_:with:) 메서드를 보면 알다시피 중간 흔들림에 대해서는 보고하지 않는다.

그래서 연속으로 두번을 흔들지 않아도 횟수가 누적되면 실행되도록 구현하였다.

출처 :

iOS ShakeGesture

[iOS] motion gesture 감지하기

iOS의 Responder와 Responder Chain 이해하기

깃허브 :

GitHub - 28th-SOPT-iOS-CloneCoding/MiraClone-KimHyunGyu: 🧚 아요 미라클론코딩 김현규

Categories:

Updated: