ios - uipangesturerecognizer swift 4
Cómo eliminar todos los reconocedores de gestos de una UIView en Swift (3)
ACTUALIZACIÓN PARA iOS 11
En general, es (y siempre ha sido) una mala idea eliminar todos los reconocimientos de gestos de una vista mediante un bucle a través de su matriz gestureRecognizers
. Solo debe eliminar los reconocedores de gestos que agregue a la vista, haciendo un seguimiento de esos reconocedores en su propia variable de instancia.
Esto adquiere una nueva importancia en iOS 11 para las vistas que están involucradas en la función de arrastrar y soltar, ya que UIKit agrega sus propios reconocedores de gestos a esas vistas para reconocer los drags y drops.
ACTUALIZAR
Ya no es necesario UIGestureRecognizer
a UIGestureRecognizer
, porque UIView.gestureRecognizers
se cambió por el tipo [UIGestureRecognizer]?
en iOS 9.0.
Además, al usar el operador nil-coalescente ??
, puedes evitar la declaración if
.
for recognizer in subview.gestureRecognizers ?? [] {
subview.removeGestureRecognizer(recognizer)
}
Sin embargo, la forma más rápida de hacerlo es esta:
subview.gestureRecognizers?.forEach(subview.removeGestureRecognizer)
También podemos filtrar las subvistas en un ciclo for
como este:
for subview in subviews where subview is CustomSubview {
for recognizer in subview.gestureRecognizers ?? [] {
subview.removeGestureRecognizer(recognizer)
}
}
O podemos envolverlo todo en una expresión (envuelta para mayor claridad):
subviews.lazy.filter { $0 is CustomSubview }
.flatMap { $0.gestureRecognizers ?? [] }
.forEach { $0.view?.removeGestureRecognizer($0) }
El uso de .lazy
debería evitar la creación de matrices temporales innecesarias.
ORIGINAL
Esta es una de esas cosas molestas sobre Swift. Su bucle for solo funcionaría en Objective-C, pero en Swift tiene que abrir explícitamente la matriz opcional:
if let recognizers = subview.gestureRecognizers {
for recognizer in recognizers {
subview.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
Podrías desenvolverlo for recognizer in subview.gestureRecognizers!
( for recognizer in subview.gestureRecognizers!
), Pero no estoy seguro de si gestureRecognizers
puede devolver nil
y obtendrás un error de tiempo de ejecución si lo hace y lo forzas-desenvuelves.
Escribí el código Swift que intenta eliminar todos los reconocedores de gestos de todas las subvistas de un tipo de UIView personalizado.
let mySubviews = self.subviews.filter() {
$0.isKindOfClass(CustomSubview)
}
for subview in mySubviews {
for recognizer in subview.gestureRecognizers {
subview.removeGestureRecognizer(recognizer)
}
}
Pero la línea de for recognizer
produce el error del compilador:
''[AnyObject]?'' does not have a member named ''Generator''
He intentado cambiar el bucle for recognizer in enumerate(subview.gestureRecognizers)
, pero eso produce el error del compilador:
Type ''[AnyObject]?!'' Does not conform to protocol ''SequenceType''
Veo que el método gestureRecognizers
de UIView devuelve [AnyObject]??
, y creo que los valores de retorno doblemente envueltos me están haciendo tropezar. ¿Alguien puede ayudarme?
ACTUALIZACIÓN: el código de compilación revisado es:
if let recognizers = subview.gestureRecognizers {
for recognizer in recognizers! {
subview.removeGestureRecognizer(recognizer as UIGestureRecognizer)
}
}
La solución más simple
yourView.gestureRecognizers?.removeAll()
Una forma más simple de hacerlo es
for subview in self.subviews as [UIView] {
if subview.isKindOfClass(CustomSubview) {
subview.gestureRecognizers?.removeAll(keepCapacity: false)
}
}