質問: false`や`touch.view?.isDescendant(of: subView)`の当たりなども理解ができていないまま、ただ書いてあった通りに導入したところがあるので、何が間違いか正直わかっていないところです・・・。 ただ、上記コードを書き加えても、子ビューに触れるとジェスチャーメソッドが呼ばれてしまい、状況によっては`UISlider`のツマミに触れるとアプリがクラッシュしてしまうこともありました。 ### 補足情報(言語/FW/ツール等のバージョンなど) swift3 xcode8
回答: まず以下を前提にしています。 * shouldReceiveTouch の中で使っている`subView`がどこにも定義されていないが、これは質問文でいう`親ビュー`のこと * tapGestureはちゃんとaddGestureRecognizerしている * 今自分はSwift3環境がなくてSwift4でしか動作を見てません 以上を前提にして回答します。 コードを見たところ2つ問題があると思います。 #### 問題1. shouldReceiveTouchの書き方がSwift2時代のもの 参照先の記事を見ると、 > > Swiftは2.1, Xcodeは7.1.1で書きました。 > > > とあるので、このメソッドの書き方はたぶんSwift2時代のものです。 Swift2から3の際に書き方が大きく変わったので、そのまま持ってくると大抵うまく動きません。 自分で書き換える力がない場合はできるだけSwift3と書いてあるものを参考にした方がいいと思います。 Swift3以降はこちらの書き方じゃないとダメなはずです。 ``` // Swift3以降(少なくともSwift4はこれ) func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { } ``` #### 問題2. shouldReceiveTouchの返り値が常にfalseになる if文の`touch.view?.isDescendant(of: subView)`は、**touch.viewがsubViewの子や孫ビュー、またはsubView自身だった場合**にtrueを返します。 この場合は常にtrueを返すような`touch.view`が渡ってくるはずなので、必ずif文の中を通ることになって`return false`することになります。 返り値がfalseになると、tapGestureはジェスチャを処理せず、`#selector`のメソッドが呼ばれません。 #### 回答 目的の**親ビューにaddしたジェスチャーメソッドを子ビューに完全に反映しない**という動作は、言い換えると**親ビュー(subView)以外の子ビューがタップされた時はジェスチャーを処理しないで、親ビューがタップされた時のみ処理する**という動作になると思います。 ということで、shouldReceiveTouchメソッドをこうすればいいんじゃないでしょうか。 ``` func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool { if touch.view != subView { // 親ビュー(subView)以外の子ビューがタップされた return false } // 親ビューがタップされた return true } ```