watchOS 3 で追加された WKGestureRecognizer でタッチ操作を検知してみる

※本記事は、[一般に公開されている情報](https://developer.apple.com/reference/watchkit/wkgesturerecognizer)を元に作成しています

# これは何

watchOS のバージョンも 3.0 になり、ようやく Gesture Recognizer が使えるようになりました。

* WKLongPressGestureRecognizer
* WKPanGestureRecognizer
* WKSwipeGestureRecognizer
* WKTapGestureRecognizer

それぞれの実装方法をメモします。

## 動作環境

* Xcode 8.0 beta 1
* watchOS 3.0 beta 1

# 状態

Gesture Recognizer は `state` プロパティを持っており、様々な状態がセットされます。

```swift
public enum WKGestureRecognizerState : Int {

    
    case possible // = UIGestureRecognizerStatePossible

    case began // = UIGestureRecognizerStateBegan

    case changed // = UIGestureRecognizerStateChanged

    case ended // = UIGestureRecognizerStateEnded

    case cancelled // = UIGestureRecognizerStateCancelled

    case failed // = UIGestureRecognizerStateFailed

    case recognized // = UIGestureRecognizerStateRecognized
}
```

状態が変化する順序は Gesture Recognizer  の種類によって異なり、デリゲートメソッドが呼ばれる回数も違ってくるので、実装する際は注意が必要です。

# 実装

## Gesture Recognizer 追加

Gesture Recognizer を追加する方法は iOS と同じです。Xcode 右下部にある Object Library から Gesture Recognizer を対象のオブジェクトにドラッグするだけです。 **（NDA期間なのでスクリーンショットを載せるのは自粛します）**

あとは、アクションメソッドに接続するだけです。

```
@IBAction func handleGesture()
@IBAction func handleGesture(gestureRecognizer : WKGestureRecognizer)
```

`gestureRecognizer ` には各種 `WKGestureRecognizer ` オブジェクトが返ってくるので、ここからタッチ位置などを取得することができます。

## WKLongPressGestureRecognizer

いわゆる「長押し」を検知します。`State` は次のように変化します。

* Possible —> Began —> [Changed…] —> Ended
* Possible —> Began —> [Changed…] —> Failed

次の属性を設定できます。

* Min Duration - 最低何秒タッチし続ける必要があるか
* Taps - 何回タッチする必要があるか
* Movement - 長押し中にどのくらい指の移動を許容するか



[WKLongPressGestureRecognizer - Apple Developer Documentation](https://developer.apple.com/reference/watchkit/wklongpressgesturerecognizer)

## WKPanGestureRecognizer

パンジェスチャー（いわゆる「ドラッグ」）を検知します。`State` は次のように変化します。


* Possible —> Began —> [Changed…] —> Ended
* Possible —> Began —> [Changed…] —> Failed

移動先の座標は

```swift
public func translationInObject() -> CGPoint
```

で取得できます。`locationInObject ` とは異なり、最初にタッチした位置が `(0, 0)` になります。

使用例：

```swift
@IBAction func panRecognized(_ sender: AnyObject) {
    if let panGesture = sender as? WKPanGestureRecognizer {
        panLabel.setText("offset: \(NSStringFromCGPoint(panGesture.translationInObject()))")
    }
}
```

[WKPanGestureRecognizer - Apple Developer Documentation](https://developer.apple.com/reference/watchkit/wkpangesturerecognizer)

## WKSwipeGestureRecognizer

スワイプジェスチャーを検知します。`State` は次のように変化します。

* Possible —> Recognized
* Possible —> Failed

次の属性を設定できます。

* Swipe - 検知するスワイプの方向

[WKSwipeGestureRecognizer - Apple Developer Documentation](https://developer.apple.com/reference/watchkit/wkswipegesturerecognizer)

## WKTapGestureRecognizer

`State` は次のように変化します。

* Possible —> Recognized
* Possible —> Failed

次の属性を設定できます。

* Taps - タップ回数。例えば `2` を設定するとダブルタップのみ検知する

タップ位置は

```swift
public func locationInObject() -> CGPoint
```

で取得できます。

[WKTapGestureRecognizer - Apple Developer Documentation](https://developer.apple.com/reference/watchkit/wktapgesturerecognizer)

# リンク

* [WKGestureRecognizer - Apple Developer Documentation](https://developer.apple.com/reference/watchkit/wkgesturerecognizer)
* [WatchKit Catalog: Using WatchKit Interface Elements](https://developer.apple.com/library/prerelease/content/samplecode/WKInterfaceCatalog/Introduction/Intro.html) - サンプルコードが参考になります
* [【watchOS 3】API Diffsから見る watchOS 3 の新機能 #WWDC2016 - Over&Out その後](http://d.hatena.ne.jp/shu223/20160614/1465887566)　- shu223さんによる素晴らしい記事