recognizer ios uiview swift uigesturerecognizer optional

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) } }