Comment enlever tous les reconnaisseurs de gestes d'un UIView dans Swift

J'ai écrit le code Swift qui tente de supprimer tous les reconnaisseurs de gestes de toutes les sous-vues d'un type UIView personnalisé donné.

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

Mais la ligne de for recognizer produit l'erreur du compilateur:

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

J'ai essayé de changer la boucle de for recognizer in enumerate(subview.gestureRecognizers) , mais cela produit l'erreur du compilateur:

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

Je vois que la méthode gestureRecognizers de gestureRecognizers renvoie [AnyObject]?? , et je pense que les valeurs de return doublement emballées me font trébucher. Quelqu'un peut-il m'aider?

MISE À JOUR: Révisé, le code de compilation est:

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

MISE À JOUR POUR iOS 11

En général, il est (et a toujours été) une mauvaise idée de supprimer tous les gestes reconnus d'une vue en bouclant son tableau gestureRecognizers . Vous ne devez supprimer que les reconnaisseurs de gestes que vous ajoutez à la vue, en conservant la trace de ces outils de reconnaissance dans votre propre variable d'instance.

Cela prend une nouvelle importance dans iOS 11 pour les vues qui sont impliquées dans le glisser-déposer, car UIKit ajoute ses propres reconnaisseurs de gestes à ces vues pour reconnaître les pertes et les chutes.

METTRE À JOUR

Vous n'avez plus besoin de UIGestureRecognizer en UIGestureRecognizer , parce que UIView.gestureRecognizers été changé en type [UIGestureRecognizer]? dans iOS 9.0.

En outre, en utilisant l'opérateur nil-coalescing ?? , vous pouvez éviter l'instruction if .

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

Cependant, le moyen le plus court de le faire est le suivant:

 subview.gestureRecognizers?.forEach(subview.removeGestureRecognizer) 

Nous pouvons aussi faire le filtrage des sous-vues dans une boucle for comme ceci:

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

Ou nous pouvons tout envelopper dans une seule expression (enveloppé pour plus de clarté):

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

L'utilisation de .lazy devrait l'empêcher de créer des arrays temporaires inutiles.

ORIGINAL

C'est une de ces choses agaçantes à propos de Swift. Votre boucle for fonctionnerait simplement dans Objective-C, mais dans Swift vous devez déplier explicitement le tableau optionnel:

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

Vous pourriez forcer-déballer ( for recognizer in subview.gestureRecognizers! ), Mais je ne suis pas sûr que gestureRecognizers puisse renvoyer nil et vous obtiendrez une erreur d'exécution si c'est le cas et vous forcez-le déballer.

Une façon plus simple de le faire est

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

La solution la plus simple

 yourView.gestureRecognizers?.removeAll()