addTarget은 UIControl 객체만 적용할 수 있지만 addGestureRecognizer은 UIView 객체에 모두 적용가능하다.
Subclass
기본적으로 정의되어있는 subClass는 7개가 존재
단순 제스처를 인식하는 것은 Discrete, 제스처의 변경을 인식하고자 하면 Continuous를 사용
Discrete
UITapGestureRecognizer
UISwipeGestureRecognizer
Continuous
UIPinchGestureRecognizer
UIRotationGestureRecognizer
UIPanGestureRecognizer
UIScreenEdgePanGestureRecognizer
UILongPressGestureRecognizer
UIPanGestureRecognizeer
panning gesture를 해석하는 연속 제스처 인식기이다.
UIPanGestrueRecognizer은 UIGestrueRecognizer의 구체적인 하위 클래스이다.
이 클래스의 클라이언트는 액션 메서드에서 UIPanGestureRecognizer 객체에 제스처의 현재 변환(translation(in:))과 변환의 속도(velocity(in:))를 쿼리할 수 있고, 변환과 속도 값에 사용할 뷰의 좌표계를 지정할 수 있다.
클라이언트는 원하는 값으로 변환을 재설정할 수도 있다.
panning gesture는 연속적이다. 사용자는 뷰를 panning하는 동안, 하나 이상의 손가락을 뷰에 눌러야 한다. 사용자가 팬으로 인식할 수 있는 충분한 거리만큼 허용된 최소 손가락 수(minimumNumverOfTouches)를 움직이면 제스처가 시작된다.(UIGetstureRecognizer.State.began)
사용자가 최소 손가락 수로 누른 상태에서 손가락을 움직이면 UIGestureRecognizer.changed상태로 변경된다. 사용자가 모든 손가락을 들어올리면, 종료(UIGetstureRecognizer.ended)된다.
Handle UIPanGestureRecognizer
팬 제스처는 사람이 하나 또는 더 많은 손가락들을 스크린주변에 움직일때마다 발생한다. 스크린 엣지 팬 제스처는 화면의 가장자리에서 시작하는 특수한 팬 제스처이다. 팬 제스처에는 UIPanGestureRecognizer클래스를 사용하고 엣지팬제스처에는 UIScreenEdgePanGestureRecognizer 클래스를 사용한다.
아래 방법들로 제스처 인식기를 붙일 수 있다.
해당 뷰의 addGestureRecognizer(_:)메서드를 호출한다.
Interface Builder안, 라이브러리로부터 해당객체를 끌어다 해당뷰위에 놓는다.
화면에서 사용자 손가락의 움직임을 추적해야하는 작업에는 팬 제스처 인식기를 사용한다. 팬 제스처 인식기를 사용하여 인터페이스에서 물체를 드래그하거나 사용자 손가락의 위치를 기반으로 포지션을 업데이트할 수 있다.
팬 제스처는 연속적이므로, 터치정보가 변경될 때마다 액션메서드가 호출되어 콘텐츠를 업데이트할 수 있다.
팬 제스처 인식기는 필요한 양의 초기 이동이 이루어지자마자 UIGestureRecognizer.State.began 상태로 들어간다.해당 초기 변경 후, 이후 변경은 제스처 인식기가 UIGestureRecognizer.State.changed상태로 들어간다.
사용자의 손가락이 화면으로부터 들어올려졌을 때, 제스처 인식기는 UIGestureRecognizer.State.ended 상태로 들어간다.
추적을 단순화하기위해, 제스처 인식기의 translation(in:)메서드를 사용하여 사용자의 손가락이 원래 터치 위치로부터 이동한 거리를 얻는다. 제스처를 시작할 때, 팬 제스처 인식기는 사용자의 손가락들에 대한 초기 접촉 포인트를 저장한다. (제스처가 여러 손가락들을 포함하는 경우, 제스처 인식기는 터치들의 세트의 중심점을 사용한다.) 손가락들이 움직일 때마다, translation(in:)메서드는 원래 위치로부터의 거리를 보고한다.
아래 코드는 화면 주위로 뷰를 드래그하는데 사용된 액션메서드를 보여준다. 제스처를 시작할 때, 이 메서드는 그 뷰의 초기 포지션을 저장한다. 그런 다음에, 사람의 손가락의 움직임을 기반으로 뷰의 포지션을 업데이트 한다.
var initialCenter = CGPoint() // The initial center point of the view.
@IBAction func panPiece(_ gestureRecognizer : UIPanGestureRecognizer) {
guard gestureRecognizer.view != nil else {return}
let piece = gestureRecognizer.view!
let translation = gestureRecognizer.translation(in: piece.superview) //슈퍼뷰의 좌표공간에 대한 x방향과 y방향의 변화를 가져온다.
if gestureRecognizer.state == .began {
// Save the view's original position.
self.initialCenter = piece.center
}
// Update the position for the .began, .changed, and .ended states
if gestureRecognizer.state != .cancelled {
// Add the X and Y translation to the view's original position.
let newCenter = CGPoint(x: initialCenter.x + translation.x, y: initialCenter.y + translation.y)
piece.center = newCenter
}
else {
// On cancellation, return the piece to its original location.
piece.center = initialCenter
}
}
팬 제스처 인식기의 코드가 호출되지 않는 경우, 다음 조건이 사실인지 확인하고 필요에 따라 수정한다.
뷰의 isUserInterationEnabled 속성은 true로 설정된다. 이미지뷰와 label들은 이 속성을 기본적으로 false로 설정한다.
터치 횟수는 minimumNumberOfTouches속성과, maximumNumberOfTouches속성에 지정된 값 사이이다.
UIScreenEdgePanGestureRecognizer객체의 경우, 엣지 속성이 구성되고, 터치들이 적절한 엣지에서 시작된다.
속성
var maximumNumberOfTouches: Int
제스처 인식을 위해 뷰를 터치할 수 있는 최대 손가락 수.
var minimumNumberOfTouches: Int
제스처 인식을 위해 뷰를 터치할 수 있는 최소 손가락 수
메서드
func translation(in: UIView?) → CGPoint
지정된 뷰의 좌표계에서 팬 제스처를 해석한다.
파라미터
view : 팬 제스처의 변환이 계산되어야 하는 좌표계의 뷰이다. 뷰의 위치를 조정하여 사용자의 손가락 아래에 유지하려면 해당 뷰의 슈퍼뷰의 좌표계에서 변환을 요청한다.
리턴 값
지정된 슈퍼뷰의 좌표계에서 뷰의 새 위치를 식별하는 point이다.’
주의
x및 y값은 시간 경과에 따른 총 변환을 보고한다. 이는 변환이 보고된 마지막 시간의 델타값이 아니다.
제스처가 처음 인식될 때, 변환값을 뷰의 상태에 적용한다. 핸들러가 호출될 때마다 값을 연결하지 마라.
func setTranslation(_: CGPoint, in: UIView?)
지정된 뷰의 좌표계에서 변환 값을 설정한다.
파라미터
translation
새로운 변환값을 식별하는 지점
view
변환이 발생할 좌표계의 뷰
주의
변환값을 변경하는것은 팬의 속도를 재 설정한다.
func velocity(in: UIVIew?) → CGPoint
지정된 뷰의 좌표계에서 팬 제스처의 속도를 해석한다.
파라미터
view: 팬 제스처의 속도를 계산하는 좌표계의 뷰이다.
리턴값
팬 제스처의 속도는 초당 포인트로 표시된다. 속도는 수평 및 수직 구성요소로 나뉜다.
Pan 제스처는 Drag와 비슷한 개념
View를 Panning하기 위해서는 하나 이상의 손가락이 필요함, 최소 하나 이상이기 때문에 설정에 따라 2,3 개 손가락도 가능함
Pan제스처로 인식되기 위해서는 설정된 최소 손가락수로 설정된 최소거리는 움직여야 함
minimumNumberOfTouches, maxmumNumberOfTouch로 각각 최소 손가락 수, 최대 손가락 수를 설정할 수 있다.
began 상태에서 손가락을 움직일 때마다 changed로 변경이 되고, 손을 떼면 ended로 변경된다.
Pan 제스처 인식조건
began : 설정된 손가락 수로 설정된 거리를 이동한 시점
changed: began 이후 손가락을 움직일때마다
ended: 손을 뗀 시점
→ 인식이 되면 recognizer 인스턴스의 translation(in:) 메서드를 사용하여 초기 위치(began페이즈로 진입한 시점의 터치 위치)로부터 이동한 거리를 얻을 수 있다.
state가 began으로 설정될 때의 터치위치를 저장하기 때문에 이후 translation(in:)메서드에서 저장된 원래위치로부터 거리를 얻을 수 있음
translation(in:)메서드는 CGPoint타입을 반환하는데, 이때 x,y값을 사용하여 이동한 거리를 구해 contents를 이동할 수 있다.
중요한것은 꼭 setTranslation(:, in:)메서드를 사용하여야하는데, 이때 translation(.zero, in: recognizerView)를 해주어야한다.
왜 zero로 해주냐면, PanGestureRecognizer의 translation값은 이전 값에서 얼마나 떨어졌는 지가 아니라, state began단계일 때의 점, 즉 원점에서 얼마나 떨어졌는지를 나타내는 값이기 때문임.
움직이고자하는 View를 포함한 contents에 이 translation값을 사용하여 변화를 주었다면, 그 시점에서 변화된 contents의 translation을 0으로 주어, 즉 이 지점이 새로운 원점임을 알려주어야 의도대로 이동할 수 있다.