web-dev-qa-db-ja.com

SwiftのUIViewからすべてのジェスチャレコグナイザーを削除する方法

特定のカスタムUIViewタイプのすべてのサブビューからすべてのジェスチャレコグナイザーを削除しようとするSwiftコードを記述しました。

_let mySubviews = self.subviews.filter() {
   $0.isKindOfClass(CustomSubview)
}
for subview in mySubviews {
   for recognizer in subview.gestureRecognizers {
      subview.removeGestureRecognizer(recognizer)
   }
}
_

ただし、_for recognizer_行はコンパイラエラーを生成します。

_'[AnyObject]?' does not have a member named 'Generator'
_

_for recognizer_ループをfor recognizer in enumerate(subview.gestureRecognizers)に変更しようとしましたが、コンパイラエラーが発生します。

_Type '[AnyObject]?!' Does not conform to protocol 'SequenceType'
_

UIViewのgestureRecognizersメソッドが_[AnyObject]??_を返すことがわかり、二重にラップされた戻り値が私をつまずかせていると思います。誰も私を助けることができますか?

更新:改訂されたコンパイルコードは次のとおりです。

_if let recognizers = subview.gestureRecognizers {
   for recognizer in recognizers! {
      subview.removeGestureRecognizer(recognizer as UIGestureRecognizer)
   }
}
_
48

IOS 11の更新

一般的に、(allジェスチャーがビューからgestureRecognizers配列をループすることで認識する)を削除するのは(そしてこれまでずっと)悪い考えです。 yoビューに追加するジェスチャレコグナイザーのみを削除する必要があります。これらのレコグナイザーを追跡するには、独自のインスタンス変数を使用します。

これは、UIKitが独自のジェスチャー認識機能をそれらのビューに追加してドラッグアンドドロップを認識するため、iOS 11でドラッグアンドドロップに関係するビューにとって新たな重要性を帯びます。

更新

UIView.gestureRecognizersはiOS 9.0で[UIGestureRecognizer]?型に変更されたため、UIGestureRecognizerにキャストする必要はなくなりました。

また、nil-coalescing演算子??を使用することにより、ifステートメントを回避できます。

for recognizer in subview.gestureRecognizers ?? [] {
    subview.removeGestureRecognizer(recognizer)
}

ただし、これを行う最短の方法は次のとおりです。

subview.gestureRecognizers?.forEach(subview.removeGestureRecognizer)

次のようなforループでサブビューのフィルタリングを行うこともできます。

for subview in subviews where subview is CustomSubview {
    for recognizer in subview.gestureRecognizers ?? [] {
        subview.removeGestureRecognizer(recognizer)
    }
}

または、すべてを1つの式にまとめることができます(わかりやすくするためにラップしています)。

subviews.lazy.filter { $0 is CustomSubview }
    .flatMap { $0.gestureRecognizers ?? [] }
    .forEach { $0.view?.removeGestureRecognizer($0) }

.lazyを使用すると、不要な一時配列が作成されなくなります。

元の

これは、Swiftの面倒なことの1つです。 forループはObjective-Cで機能しますが、Swiftではオプションの配列を明示的にアンラップする必要があります。

if let recognizers = subview.gestureRecognizers {
    for recognizer in recognizers {
        subview.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
    }
}

強制的にアンラップできます(for recognizer in subview.gestureRecognizers!)が、gestureRecognizersnilを返すことができるかどうかわかりません。ラップを解除します。

97
rob mayoff

最も簡単なソリューション

yourView.gestureRecognizers?.removeAll()
27
user3144836

それを行う簡単な方法は

for subview in self.subviews as [UIView] {
    if subview.isKindOfClass(CustomSubview) {
        subview.gestureRecognizers?.removeAll(keepCapacity: false)
    }
}
10
Ah Ryun Moon