UITableViewCell内の画像がタップされた時にUITableViewの行番号を取得するいくつかの方法


UITableViewCell内の画像をタップした時に行番号を取得する方法をいくつか紹介します。

## 準備

1. `UItableViewCell`に`UIImageView`を配置します。

2. 配置した`UIImageView`からコードに対してoutletを定義します。

    このページでは`icon`という名前にします。

    ```swift
    @IBOutlet weak var icon: UIImageView!
    ```

3. 上記`UIImageView`のuser interactionを有効にしておきます。(コードで実装する場合は省略)

    [UIImageにTapGestureを指定したのに、反応してくれなくて困ったとき](http://qiita.com/mm36/items/605794a1b6d967c49f27)


## パターン1. UITableViewControllerの中で実装

UITableViewControllerの中で素直に取得します。

```swift
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
	let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! SampleTableViewCell

    if cell.icon.gestureRecognizers?.count == 0 { //重複登録チェック(※)
        //gestureを設定
        let tapGesture = UITapGestureRecognizer(target: self, action: Selector("tapIcon:"))
        cell.icon.addGestureRecognizer(tapGesture)
        cell.icon.userInteractionEnabled = true
    }
    return cell
}
```

※ 重複登録を防ぐために`gestureRecognizers`で`UIImageView`に登録されたジェスチャーを取得しています。ここでは簡略のために`gestureRecognizers?.count`で`UIImageView`に登録されたジェスチャーの個数だけをチェックしていますが、複数タイプのジェスチャーを登録する場合など厳密にチェックしたい場合は`gestureRecognizers`の中を見て判定した方が良いです。

```swift

func tapIcon(gestureRecognizer: UITapGestureRecognizer) {
    let tappedLocation = gestureRecognizer.locationInView(tableView)
    let tappedIndexPath = tableView.indexPathForRowAtPoint(tappedLocation)
    let tappedRow = tappedIndexPath?.row
    print(tappedRow)
}
```

※ [mm36](http://qiita.com/mm36)さんにアドバイスもらいました。ありがとうございます。

## パターン2. UITableViewCellの中で実装

UITableViewCellから自分のいるUITableViewControllerを取得します。

```swift

override func awakeFromNib() {
    super.awakeFromNib()
    	// 略

	//gestureを設定
    let tapGesture = UITapGestureRecognizer(target: self, action: Selector("tapIcon:"))
    tapGesture.delegate = self;
    icon.addGestureRecognizer(tapGesture)
}
```

```swift

func tapIcon(sender: UITapGestureRecognizer) {
    let tableView = superview?.superview as! UITableView //UITableViewを取得
    let tappedIndexPath = tableView.indexPathForCell(self) //自分のIndexPathを取得
    let tappedRow = tappedIndexPath?.row //IndexPathから行を取得
    debugPrint(tappedRow)
}
```

## パターン3. レスポンダチェーンを使ってUIImageViewからUITableViewControllerにイベントを送る

1. UITableViewCell内のUIImageViewにタップのジェスチャーを設定します。
2. タップされたらレスポンダチェーンに`sendAction`して、`UITableViewController`に来た時点で受け取って任意の処理を行います。

@tomohisaota さんからアドバイスいただきました。ありがとうございます。

`UITableViewCell`内の実装

```swift

override func awakeFromNib() {
    super.awakeFromNib()
    	略
	
	//ジェスチャーの登録
	icon.userInteractionEnabled = true
	let tapGesture = UITapGestureRecognizer(target: self, action: Selector("iconTapped:"))
	icon.addGestureRecognizer(tapGesture)
}

// ジェスチャーのアクション
@IBAction func iconTapped(sender: AnyObject) {
	//レスポンダチェーンにアクションを送信		
	UIApplication.sharedApplication().sendAction("iconTappedAction:", to: nil, from: icon, forEvent: nil)
}
```

`UITableViewController`内の実装

```swift

func iconTappedAction(sender:AnyObject?) {
    guard let gestures = sender?.gestureRecognizers! else { return }
    for gesture in gestures {
        if let gesture = gesture as? UITapGestureRecognizer {
            let tappedLocation = gesture.locationInView(tableView)
            let tappedIndexPath = tableView.indexPathForRowAtPoint(tappedLocation)
            let tappedRow = tappedIndexPath?.row
            debugPrint(tappedRow)
        }
    }
}
```