【iOS】UITapGestureの共存


## iOS その3 Advent Calendar

5日目を書かせて頂きます！

- [UIImageの加工について - Qiita](http://qiita.com/ryokosuge/items/29b88369a2cf61b6b215)
- [UITableViewのSectionHeaderとSectionFooterをdequeuで使いまわしできるようにする - Qiita](http://qiita.com/ryokosuge/items/3dabb9875b32a0908bce)

を書かせてもらっています！

では本題に入ります。

## １つのViewでシングルタップとダブルタップを検知したい

ってことが前にありました。

普通にかくと以下のようになると思います。

```swift:ViewController.swift
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleSingleTapGesture(_:)))
        singleTapGesture.numberOfTapsRequired = 1
        singleTapGesture.numberOfTouchesRequired = 1
        view.addGestureRecognizer(singleTapGesture)
        
        let doubleTapGesture = UITapGestureRecognizer(target: self , action: #selector(ViewController.handleDoubleTapGesture(_:)))
        doubleTapGesture.numberOfTapsRequired = 2
        doubleTapGesture.numberOfTouchesRequired = 1
        view.addGestureRecognizer(doubleTapGesture)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // single tap
    @IBAction func handleSingleTapGesture(_ gesture: UITapGestureRecognizer) {
        print("single tap")
    }
    
    @IBAction func handleDoubleTapGesture(_ gesture: UITapGestureRecognizer) {
        print("double tap")
    }

}
```

ただ上記のように実装すると以下のようにログが流れます。

![12月-03-2016 23-06-52.gif](https://qiita-image-store.s3.amazonaws.com/0/47302/37547c69-e0a8-7af5-ceaa-e7d9181ae93d.gif)

わかりづらいかもですが、**doubleTapGesture**のイベントの前にも必ず**singleTapGesture**の処理が入っていることです。

望んでいるのは**doubleTapGesture**が動作するときは**singleTapGesture**は反応して欲しくないのです。

## ということで手を加える

以下のように実装すると僕が望んだ通りの処理になりました。

```swift:ViewController.swift
class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        let singleTapGesture = UITapGestureRecognizer(target: self, action: #selector(ViewController.handleSingleTapGesture(_:)))
        singleTapGesture.numberOfTapsRequired = 1
        singleTapGesture.numberOfTouchesRequired = 1
        view.addGestureRecognizer(singleTapGesture)
        
        let doubleTapGesture = UITapGestureRecognizer(target: self , action: #selector(ViewController.handleDoubleTapGesture(_:)))
        doubleTapGesture.numberOfTapsRequired = 2
        doubleTapGesture.numberOfTouchesRequired = 1
        view.addGestureRecognizer(doubleTapGesture)
        
        // こいつを加える！！
        singleTapGesture.require(toFail: doubleTapGesture)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // single tap
    @IBAction func handleSingleTapGesture(_ gesture: UITapGestureRecognizer) {
        print("single tap")
    }
    
    @IBAction func handleDoubleTapGesture(_ gesture: UITapGestureRecognizer) {
        print("double tap")
    }

}
```

すると以下のようになります。

![12月-03-2016 23-11-46.gif](https://qiita-image-store.s3.amazonaws.com/0/47302/3f28fbb2-3cd1-b051-93ca-769259233a44.gif)

ログが重複しなくりました！

## 懸念点

今回加えた`UIGestureRecognizer`の`func require(toFail otherGestureRecognizer: UIGestureRecognizer)`は以下のように説明がありました。

> Creates a dependency relationship between the receiver and another gesture recognizer when the objects are created.
>
> <cite><a href="https://developer.apple.com/reference/uikit/uigesturerecognizer/1624203-require">require(toFail:) - UIGestureRecognizer | Apple Developer Documentation</a>より</cite>

最近とても優秀なGoogle翻訳にかけると

> 受信者と別のジェスチャ認識プログラムがオブジェクトの作成時に依存関係を作成します。

となりました。

簡単にソースコードの意味で説明すると

`singleTapGesture.require(toFail: doubleTapGesture)`は`doubleTapGesture`が`Fail`したら`singleTapGesture`が実行されるという依存関係を結んだということになりますかね...。

最近betaツールでスクショを送れたりページにコメントできたりというのがあって、３本指でタップしたらなどのイベントを生成していると思いますが、かぶることもあり得るのでここら辺上記のメソッドで依存関係を一番最後に回すようなことを考えたら楽になりそうだなって思ったり...。

## 最後に

*GIPHY CAPTURE*とっても便利でした。

以上です。