Apple Pencil 向けの API

# はじめに

Pencil の実物が手元にないので API を眺めるのみ。

馴染みない単語：

> Azimuth… 方位角
> Altitude… 高度

![図](https://upload.wikimedia.org/wikipedia/commons/thumb/f/f7/Azimuth-Altitude_schematic.svg/498px-Azimuth-Altitude_schematic.svg.png)

この図に `Observer` を筆先、`Star` を Lightning 端子と当てはめれば良いのかな。

# UITouch

## UITouchType

タッチの種別に Stylus（≒Apple Pencil）が追加された。

```objc:UITouchType
typedef NS_ENUM(NSInteger, UITouchType) {
    UITouchTypeDirect,                       // A direct touch from a finger (on a screen)
    UITouchTypeIndirect,                     // An indirect touch (not a screen)
    UITouchTypeStylus NS_AVAILABLE_IOS(9_1), // A touch from a stylus
} NS_ENUM_AVAILABLE_IOS(9_0);
```

- **UITouchTypeDirect**: 指タッチ
- **UITouchTypeIndirect**: 詳細不明
- **UITouchTypeStylus**: Pencil

`UITouchTypeIndirect` に関しての記述は特になく、用途不明。「スクリーン外の間接的なタッチ」という旨のコメントがあるので、キーボードのフォースタッチか、あるいは将来 Siri Remote のようなデバイスに対応するためのものなのかもしれない。

## より精度の高いタッチ座標を求める

```swift:UITouch
// Use these methods to gain additional precision that may be available from touches.
// Do not use precise locations for hit testing. A touch may hit test inside a view, yet have a precise location that lies just outside.
@available(iOS 9.1, *)
public func preciseLocationInView(view: UIView?) -> CGPoint
@available(iOS 9.1, *)
public func precisePreviousLocationInView(view: UIView?) -> CGPoint
```

### 精度の高い座標とは

iOS 9.1 より、指と Pencil 両方でより正確で精度の高いタッチ座標を得ることができる。これは既存の `-locationInView:` の代わりに上記のメソッドを使用するだけで良い。大きな画面を持つ端末には有効。

**それぞれのメソッドの対応**

| |通常のタッチ座標|高精度なタッチ座標|
|---|---|---|
|現在のタッチ座標|locationInView()|preciseLocationInView()|
|直前のタッチ座標|previousLocationInView()|precisePreviousLocationInView()|


## 方位角（Azimuth）を得る

方位角を得る。UITouchTypeStylus のみで有効。

```swift:UITouch
// Azimuth angle. Valid only for stylus touch types. Zero radians points along the positive X axis.
// Passing a nil for the view parameter will return the azimuth relative to the touch's window.
@available(iOS 9.1, *)
public func azimuthAngleInView(view: UIView?) -> CGFloat
```

方位角の方向を指す単位ベクトルを得る。UITouchTypeStylus のみで有効。

```swift:UITouch
// A unit vector that points in the direction of the azimuth angle. Valid only for stylus touch types.
// Passing nil for the view parameter will return a unit vector relative to the touch's window.
@available(iOS 9.1, *)
public func azimuthUnitVectorInView(view: UIView?) -> CGVector
```

参考までに CGVector

```swift:CGGeometry
public struct CGVector {
    public var dx: CGFloat
    public var dy: CGFloat
    public init()
    public init(dx: CGFloat, dy: CGFloat)
}
```

## 高度角（Altitude）を得る

高度角を得る。UITouchTypeStylus のみで有効。
`M_PI/2` ラジアンは Pencil が画面に垂直であることを示す。0ラジアンは Pencil が画面と平行であることを示す。

```swift:UITouch
// Altitude angle. Valid only for stylus touch types.
// Zero radians indicates that the stylus is parallel to the screen surface,
// while M_PI/2 radians indicates that it is normal to the screen surface.
@available(iOS 9.1, *)
public var altitudeAngle: CGFloat { get }
```

### [備考：ラジアン／弧度法](https://ja.wikipedia.org/wiki/ラジアン)

![radian](https://upload.wikimedia.org/wikipedia/commons/4/4e/Circle_radians.gif)

## estimationUpdateIndex

このプロパティは、推定プロパティを含む各タッチでただ増加します。適切なタッチにタッチアップデートを適用することを確認するために、このプロパティを使用することができる。オブジェクトが推定または更新されたプロパティのいずれかが含まれていないときにnilを返す。（Google翻訳）

……ということで、タッチのインデックス的なものらしい。

```swift:UITouch
// An index which allows you to correlate updates with the original touch.
// Is only guaranteed non-nil if this UITouch expects or is an update.
@available(iOS 9.1, *)
public var estimationUpdateIndex: NSNumber? { get }
```

## UITouchProperties

推定プロパティのビットマスク。

```swift:UITouchProperties
@available(iOS 9.1, *)
public struct UITouchProperties : OptionSetType {
    public init(rawValue: Int)
    
    public static var Force: UITouchProperties { get }
    public static var Azimuth: UITouchProperties { get }
    public static var Altitude: UITouchProperties { get }
    public static var Location: UITouchProperties { get } // For predicted Touches
}
```

それぞれ Pencil の筆圧、方位、高度、座標 を表す。

## estimatedProperties

推定プロパティを得る。

```swift:UITouch
// A set of properties that has estimated values
// Only denoting properties that are currently estimated
@available(iOS 9.1, *)
public var estimatedProperties: UITouchProperties { get }
// A set of properties that expect to have incoming updates in the future.
// If no updates are expected for an estimated property the current value is our final estimate.
// This happens e.g. for azimuth/altitude values when entering from the edges
@available(iOS 9.1, *)
public var estimatedPropertiesExpectingUpdates: UITouchProperties { get }
```

# 参考資料

[UITouch Class Reference](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITouch_Class/index.html)
[What's New in iOS 9.1](https://developer.apple.com/library/ios/releasenotes/General/WhatsNewIniOS/Articles/iOS9_1.html)
[How to track finger position and touch force in iOS 9](http://pinkstone.co.uk/how-to-track-finger-position-and-touch-force-in-ios-9/)

## サンプルコード

[TouchCanvas: Using UITouch efficiently and effectively](https://developer.apple.com/library/ios/samplecode/TouchCanvas/Introduction/Intro.html)