如何从 Swift 中的 UIView 中删除所有手势识别器 [英] How to remove all gesture recognizers from a UIView in Swift
问题描述
我编写了 Swift 代码,试图从给定的自定义 UIView 类型的所有子视图中删除所有手势识别器.
I have written Swift code that attempts to remove all gesture recognizers from all subviews of a given custom UIView type.
let mySubviews = self.subviews.filter() {
$0.isKindOfClass(CustomSubview)
}
for subview in mySubviews {
for recognizer in subview.gestureRecognizers {
subview.removeGestureRecognizer(recognizer)
}
}
但是 forreceiver
行产生编译器错误:
But the for recognizer
line produces the compiler error:
'[AnyObject]?' does not have a member named 'Generator'
我尝试将 for 识别器
循环更改为 for 在 enumerate(subview.gestureRecognizers)
中的识别器,但这会产生编译器错误:
I have tried changing the for recognizer
loop to for recognizer in enumerate(subview.gestureRecognizers)
, but that produces the compiler error:
Type '[AnyObject]?!' Does not conform to protocol 'SequenceType'
我看到 UIView 的 gestureRecognizers
方法返回 [AnyObject]??
,并且我认为双重包装的返回值让我感到困惑.有人可以帮我吗?
I see that UIView's gestureRecognizers
method returns [AnyObject]??
, and I think that the doubly wrapped return values are tripping me up. Can anyone help me?
更新:修改后,编译代码为:
UPDATE: Revised, compiling code is:
if let recognizers = subview.gestureRecognizers {
for recognizer in recognizers! {
subview.removeGestureRecognizer(recognizer as UIGestureRecognizer)
}
}
推荐答案
针对 iOS 11 的更新
一般来说,通过循环遍历其 gestureRecognizers
数组来从视图中移除 all 手势识别是(并且一直是)一个坏主意.您应该只删除您添加到视图中的手势识别器,方法是在您自己的实例变量中跟踪这些识别器.
UPDATE FOR iOS 11
In general it is (and has always been) a bad idea to remove all gesture recognizes from a view by looping through its gestureRecognizers
array. You should only remove gesture recognizers that you add to the view, by keeping track of those recognizers in your own instance variable.
对于涉及拖放的视图,这在 iOS 11 中具有新的重要性,因为 UIKit 向这些视图添加了自己的手势识别器以识别拖放.
This takes on new importance in iOS 11 for views that are involved in drag and drop, because UIKit adds its own gesture recognizers to those views to recognize drags and drops.
您不再需要转换为 UIGestureRecognizer
,因为 UIView.gestureRecognizers
在 iOS 9.0 中已更改为类型 [UIGestureRecognizer]?
.
You no longer need to cast to UIGestureRecognizer
, because UIView.gestureRecognizers
was changed to type [UIGestureRecognizer]?
in iOS 9.0.
此外,通过使用 nil 合并运算符 ??
,您可以避免使用 if
语句.
Also, by using the nil-coalescing operator ??
, you can avoid the if
statement.
for recognizer in subview.gestureRecognizers ?? [] {
subview.removeGestureRecognizer(recognizer)
}
然而,最短的方法是这样的:
However, the shortest way to do it is this:
subview.gestureRecognizers?.forEach(subview.removeGestureRecognizer)
我们也可以像这样在 for
循环中过滤子视图:
We can also do the filtering of the subviews in a for
loop like this:
for subview in subviews where subview is CustomSubview {
for recognizer in subview.gestureRecognizers ?? [] {
subview.removeGestureRecognizer(recognizer)
}
}
或者我们可以将其全部包装成一个表达式(为清楚起见而包装):
Or we can wrap it all up into one expression (wrapped for clarity):
subviews.lazy.filter { $0 is CustomSubview }
.flatMap { $0.gestureRecognizers ?? [] }
.forEach { $0.view?.removeGestureRecognizer($0) }
.lazy
的使用应该可以防止它创建不必要的临时数组.
The use of .lazy
should prevent it from creating unnecessary temporary arrays.
这是 Swift 令人讨厌的事情之一.你的 for 循环只能在 Objective-C 中工作,但在 Swift 中你必须显式地解开可选数组:
This is one of those annoying things about Swift. Your for loop would just work in Objective-C, but in Swift you have to explicitly unwrap the optional array:
if let recognizers = subview.gestureRecognizers {
for recognizer in recognizers {
subview.removeGestureRecognizer(recognizer as! UIGestureRecognizer)
}
}
您可以强制解开它(用于 subview.gestureRecognizers 中的识别器!
),但我不确定 gestureRecognizers
是否可以返回 nil
如果确实如此,您将收到运行时错误,并且您将其强制解包.
You could force-unwrap it (for recognizer in subview.gestureRecognizers!
), but I'm not sure whether gestureRecognizers
can return nil
and you'll get a runtime error if it does and you force-unwrap it.
这篇关于如何从 Swift 中的 UIView 中删除所有手势识别器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!