如何从Swift中的UIView中删除所有手势识别器 [英] How to remove all gesture recognizers from a UIView in Swift

查看:141
本文介绍了如何从Swift中的UIView中删除所有手势识别器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我编写了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)
   }
}

但是 for recognizer line产生编译错误:

But the for recognizer line produces the compiler error:

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

我尝试更改识别器的 为枚举(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 方法返回rns [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 数组从视图中识别。您应该只删除添加到视图中的手势识别器,方法是跟踪您自己的实例变量中的识别器。

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.

此操作因为UIKit将自己的手势识别器添加到这些视图以识别拖放和拖放,所以iOS 11中的新功能非常重要。

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-coalescing运算符 ?? ,您可以避免 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)

我们也可以在中为循环过滤子视图:

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆