반응형
Overview
- 어떻게 멀티 터치를 지원하도록 구현할 수 있을까요?
- 어떻게 사람들이 제스처 기능을 사용할 수 있도록 구현할 수 있을까요?
Gestures
- 이전까지는 UIView가 그려지는 과정은 살펴보았지만 이번에는 어떻게 터치 이벤트를 가져올지 고민해볼 것입니다.
- 개발자는 모든 터치 이벤트를 합법적으로 가져올 수 있습니다.
- 개발자는 (touch down, moved, up 등) raw 한 터치 이벤트를 인식할 수 있습니다.
- 혹은 사전에 정의된 제스처 방식으로 해석하여 반응할 수 있습니다.
- 제스처에는 swipe, pinch, pan, tap 등이 존재합니다.
- iOS 에서 모든 제스처는 UIGestureRecognizer로 표현됩니다.
- 이 클래스는 손가락의 움직임으로 부터 제스처를 인식해주는 것이다.
- 이 클래스는 추상적이기에 이 추상 클래스를 상속하여 구현된 서브 클래스들이 제스처를 인식하는 방식에 대해 알고 있다.
- gesture recognizer 을 사용할 때에는 두가지 측면이 존재한다.
- View에게 "핀치, 탭"과 같은 것을 인식하는 것을 시작해야한다고 알려야 한다.
- 위에서 선언한 행위가 인식되었을 때 어떤 동작을 수행할지에 관한 handler 를 선언해주어야 한다.
- 첫번째의 경우 스토리보드에서 컨트롤러에 의해 수행된다. (보통 제스처를 추가할 때 사용하는 방법이다.)
- 때로는 View가 자신에게 gesture recognizer 를 추가해줄 때가 있다.
- View가 수행하는 작업이 완전히 고유한 경우이다.
- 예를 들어 스크롤 뷰가 핀치 및 패닝 제스처를 추가하는 것을 생각해볼 수 있다 (이 제스처가 없으면 스크롤 뷰가 동작하지 않는다)
- 두번째인 제스처 처리의 경우 UIView 혹은 Controller 중 하나에 의해서 제공 된다.
- 모델에 영향을 주는 경우 컨트롤러가 이를 처리한다.
- View를 보는 방식에만 영향을 주는 경우엔 View에서 직접 처리해주는 경우가 많다.
- View에 제스처를 추가해주는 방법은 무엇인가?
- 컨트롤러의 뷰가 pan 제스처를 인식하는 상황을 가정하여 생각해보자!
- UIView의 아울렛에 프로퍼티 옵저버를 붙여서 구현할 수 있다!
@IBOutlet weak var pannableView: UIView {
didSet {
let panGestureRecognizer = UIPanGestureRecognizer(
target: self, action: #selector(ViewController.pan(recognizer:))
)
pannableView.addGestureRecognizer(panGestureRecognizer)
}
}
- didSet 코드는 runtime 시에 iOS에서 outlet을 연결할 때 수행된다.
- 위 코드는 UIGestureRecognizer 서브클래스 중에서 pan 제스처를 위한 인스턴스를 사용한 예시이다.
- target 은 제스처가 인색되었을 때 알림을 받는다. (이번의 경우 컨트롤러 자신이 사용된다)
- action 은 인식된 경우에 관하여 수행될 메서드를 의미한다. 이때 인자로 들어오는 것은 recognizer 이다.
- UIView에게 자신의 bound 에서 pan 제스처를 인식하고자 시도하도록 요구한다!
- 팬이 발생되기 시작하면 핸들러가 호출됩니다.
- 제스처에 대한 핸들러는 제스처에 구체적인 정보가 필요합니다.
- 핀치 제스처에서는 핀치하는 scale, 팬 제스처는 팬이 발생하는 위치가 해당됩니다.
- 그래서 각 서브클래스들은 제스처의 타입에 관한 핸들링에 대하여 특별한 메서드를 제공합니다.
- 예를 들어, UIPanGestureRecognizer 은 3가지 메서드를 제공합니다.
- 추상적인 슈퍼 클래스(UIGestureRecognizer)는 상태 정보를 제공합니다.
- 전체 Gesture Recognizer 은 상태 머신이며 state 라는 매우 중요한 변수가 존재합니다.
- 손가락이 화면에 닿라서 팬 제스처가 가능해지는 상태면 .possible
- 지속적인 제스처가 이어지면 .began 상태에서 손가락이 움직일 때 마다 반복되는 .changed 상태를 거쳐서 손가락이 올라갈 때 .ended 상태로 전환됩니다.
- 상태 머신이 변경될 때 마다 핸들러가 호출됩니다.
- swipe 와 같은 이산적인 제스처에 관해서는, .ended 혹은 .recognized 상태로 이어집니다.
- 스와이프가 발생했는지 안했는지 별개의 개념으로 봐야 합니다.
- 손가락이 화면을 가로질러갈 때 변경되는 것이 아니라, 이산적인 제스처 여서 그냥 .ended를 얻거나, 살짝 밀어서 recognised 되거나 입니다.
- 살짝 밀어서 recognised 되면 핸들러에 신호가 한번만 전송됩니다.
- 반대로 연속 제스처의 경우 .changed 를 얻습니다.
- 흥미로운 상태로 .failed 와 .cancelled 가 존재합니다.
- .failed 는 여러개의 제스처가 존재하는 상황에서 하나가 승리할 경우 발생할 수 있습니다.
위와 같은 정보를 통해 우리가 구현할 pan handler 는 어떻게 생겼는가?
반응형
' Apple > Stanford iOS Programming (UIKit)' 카테고리의 다른 글
Lecture 13 : TableView & Collection View (0) | 2021.12.03 |
---|---|
Lecture 4 Review - More Swift (0) | 2021.12.03 |
[💻 Xcode] 🍯꿀팁 단축키 (1) | 2021.12.02 |
Lecture 2 Review: MVC (0) | 2021.12.02 |
Lecture 1 Review: Developing iOS 11 Apps with Swift (0) | 2021.12.01 |