Handling Input from Apple Pencil

Panther·2021년 8월 1일
0

https://developer.apple.com/documentation/uikit/pencil_interactions/handling_input_from_apple_pencil

"Learn how to detect and respond to touches from Apple Pencil."

애플 펜슬로부터 발생한 터치를 감지하고 이에 응답하는 방법을 알아봅니다.

Overview

UIKit은 사용자의 손가락으로부터 입력된 터치를 알려주는 방식과 동일한 방식으로 애플 펜슬의 터치를 알려줍니다. 구체적으로 UIKit은 앱에서 터치의 위치를 포함하고 있는 UITouch 객체를 전달합니다. 그러나 애플 펜슬로부터 기인한 터치 객체는 방위각, 애플 펜슬의 고도, 입력의 압력을 포함하는 추가적인 정보를 포함합니다.

Figure 1 Using stylus information as input

애플 펜슬은 분리된 기기이기 때문에 애플 펜슬이 수집하는 고도, 방위각, 압력에 대한 시간과 이에 해당하는 값이 앱에 알려지는 시간 사이에 딜레이가 있습니다. 결과적으로 UIKit은 초기에 해당 속성들에 대한 측정된 값을 제공할 것이고, 이후에서야 실제 값을 제공할 것입니다. 만약 애플 펜슬로부터 고도, 방위각, 압력 정보를 사용한다면, 측정된 속성들을 명시적으로 처리해야 합니다.

Note
애플 펜슬이 작업할 수 있는 기기는 240 Hz까지 터치를 알려줄 수 있습니다. UIKit이 보통 60 Hz 수준에서 알리기 때문에 모든 추가적인 터치들은 마지막 위치를 나타내는 하나의 터치에 통합됩니다. 추가 터치 데이터를 가져오는 방법은 Getting High-Fidelity Input with Coalesced Touches를 살펴보시기 바랍니다.

Getting High-Fidelity Input with Coalesced Touches
https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_touches_in_your_view/getting_high-fidelity_input_with_coalesced_touches
https://velog.io/@panther222128/Getting-High-Fidelity-Input-with-Coalesced-Touches

Handle Estimated Properties

UIKit이 속성의 값에 대한 측정만 갖고 있는 경우 상응하는 UITouch 객체의 estimatedPropertiesExpectingUpdates 속성에 플래그를 포함합니다. 터치 이벤트를 처리할 때, 이후에 터치 정보를 업데이트해야 하는 필요가 있는지 결정하기 위해 해당 속성을 확인하시기 바랍니다.

터치 객체가 측정된 속성들을 포함하고 있는 경우 UIKit은 또한 터치를 이후에 확인할 수 있도록 사용하는 estimationUpdateIndex 속성에 값을 제공합니다. estimationUpdateIndex 속성에서 값을 유지하고 있는 딕셔너리에 키로 사용하시기 바랍니다. 해당 키의 값을 터치 정보를 저장하기 위해 사용하는 app-specific 객체에 설정하시기 바랍니다. UIKit이 이후 실제 값을 알리게 되면, app-specific 객체를 찾기 위해 인덱스를 사용해야 하고, 측정된 값을 실제 값으로 교체해야 합니다.

Listing 1은 앱의 addSamples 메소드를 나타내고 있으며, 이 메소드는 터치 데이터를 캡처할 수 있는 메소드입니다. 각 터치에 대해 메소드는 터치 정보와 함께 커스텀 StrokeSample 객체를 생성합니다. 만약 터치의 압력 값이 오직 측정된 값이라면, registerForEstimates 메소드는 estimationUpdateIndex 속성에서 값을 키로써 사용하면서 딕셔너리에 샘플을 캐싱합니다.

Listing 1 Tracking touches that need updates

var estimates : [NSNumber : StrokeSample]
 
func addSamples(for touches: [UITouch]) {
   if let stroke = strokeCollection?.activeStroke {
      for touch in touches {
         if touch == touches.last {
            let sample = StrokeSample(point: touch.location(in: self), 
                                 forceValue: touch.force)
            stroke.add(sample: sample)
            registerForEstimates(touch: touch, sample: sample)
         } else {
            let sample = StrokeSample(point: touch.location(in: self), 
                                 forceValue: touch.force, coalesced: true)
            stroke.add(sample: sample)
            registerForEstimates(touch: touch, sample: sample)
         }
      }
      self.setNeedsDisplay()
   }
}
 
func registerForEstimates(touch : UITouch, sample : StrokeSample) {
   if touch.estimatedPropertiesExpectingUpdates.contains(.force) {
      estimates[touch.estimationUpdateIndex!] = sample
   }
}

UIKit이 터치에 대한 실제 값을 받으면, UIKit은 리스폰더 혹은 제스쳐 리코그나이저의 touchesEstimatedPropertiesUpdated(_:) 메소드를 호출합니다. 측정된 데이터를 실제 값으로 제공하기 위해 UIKit이 제공하는 해당 메소드를 사용하시기 바랍니다.

Listing 2는 Listing 1에서 생성했었던 캐싱된 StrokeSample 객체의 압력 값을 업데이트하는 touchesEstimatedPropertiesUpdated(_:) 메소드의 예시를 보여줍니다. 메소드는 측정 딕셔너리로부터 StrokeSample 객체를 회수하기 위해 estimationUpdateIndex 속성에서 값을 사용합니다. 이후 압력 값을 업데이트 하고, 딕셔너리로부터 샘플을 제거합니다.

Listing 2 Updating estimated values

override func touchesEstimatedPropertiesUpdated(_ touches: Set<UITouch>) {
   for touch in touches {
      // If the force value is no longer an estimate, update it.
      if !touch.estimatedPropertiesExpectingUpdates.contains(.force) {
         let index = touch.estimationUpdateIndex!
         var sample = estimates[index]
         sample?.force = touch.force
 
         // Remove the key and value from the dictionary.
         estimates.removeValue(forKey: index)
      }
   }
}

Topics


Computing the Perpendicular Force of Apple Pencil

압력 값이 3D 터치 압력 값에 일관적일 수 있도록 애플 펜슬에 의해 알려진 압력 값을 조정합니다.

https://developer.apple.com/documentation/uikit/pencil_interactions/handling_input_from_apple_pencil/computing_the_perpendicular_force_of_apple_pencil
https://velog.io/@panther222128/Computing-the-Computing-the-Perpendicular-Force-of-Apple-Pencil


See Also

Touches

Handling Touches in Your View

뷰의 컨텐트에 터치 처리가 복잡하게 연결되어 있는 경우 뷰 서브클래스에서 직접 터치 이벤트를 사용합니다.

https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/handling_touches_in_your_view
https://velog.io/@panther222128/Handling-Touches-in-Your-View

Tracking the Force of 3D Touch Events

터치의 압력에 기반해 컨텐트를 조작합니다.

https://developer.apple.com/documentation/uikit/touches_presses_and_gestures/tracking_the_force_of_3d_touch_events
https://velog.io/@panther222128/Tracking-the-Force-of-3D-Touch-Events

UITouch

화면에서 발생하는 터치의 위치, 크기, 움직음, 압력을 나타내는 객체입니다.

https://developer.apple.com/documentation/uikit/uitouch
https://velog.io/@panther222128/UITouch


0개의 댓글