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