if-let语句不会解包可选 [英] if-let statement doesn't unwrap optional

查看:106
本文介绍了if-let语句不会解包可选的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的代码中遇到了一些看起来很奇怪的问题,并且想知道是否对此行为有一个简单的解释.给出以下语句:

I've run across something in my code that seems curious and was wondering if there is a straightforward explanation for this behavior. Given the following statement:

    if let tabBarController = topViewController as? UITabBarController {
        for subcontroller in tabBarController.viewControllers! {
            println(subcontroller.view)
            if let subcontrollerView = subcontroller.view {
                println(subcontrollerView)
                println(subcontrollerView!)
                if subcontrollerView!.window != nil && subcontroller.isViewLoaded() {
                    topViewController = subcontroller as? UIViewController
                    break;
                }
            }
        }
    }

据我所知,if-let语句应该为我解开条件-但这不是此处显示的行为.除非再次打开可选控件,否则无法访问subcontrollerViewwindow属性. X代码控制台返回以下内容:

Now as far as I know the if-let statement should unwrap the conditional for me--but this is not the behavior exhibited here. I cannot access the window property of subcontrollerView unless I unwrap the optional again. The x-code console returns the following:

Optional(<UILayoutContainerView: 0x7fbccd44e7f0; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fbccacdde90>; layer = <CALayer: 0x7fbccd440e30>>)
Optional(<UILayoutContainerView: 0x7fbccd44e7f0; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fbccacdde90>; layer = <CALayer: 0x7fbccd440e30>>)
<UILayoutContainerView: 0x7fbccd44e7f0; frame = (0 0; 320 568); autoresize = W+H; gestureRecognizers = <NSArray: 0x7fbccacdde90>; layer = <CALayer: 0x7fbccd440e30>>  

未包装的可选内容和if-let常量相同.为什么?

The unwrapped optional and the if-let constant are the same. Why?

推荐答案

您的问题是AnyObject. (如果有疑问,您的问题始终是AnyObject;这是一种邪恶的类型,应尽可能避免.唯一糟糕的是AnyObject?.)

Your problem is AnyObject. (When in doubt, your problem is always AnyObject; it is an evil type that should be avoided as much as possible. The only thing worse is AnyObject?.)

麻烦之处在于tabBarController.viewControllers返回[AnyObject]?,并且可选的升级可能导致事情陷入困境.可能会将AnyObject?升级为AnyObject??,然后感到困惑.这在某种程度上是一个编译器错误,但也只是AnyObject随附的疯狂现象.因此,答案是尽快清除它.

The trouble is that tabBarController.viewControllers returns [AnyObject]?, and optional promotion probably causes things to go sideways. It's likely promoting an AnyObject? to an AnyObject?? and then getting confused. This is somewhat a compiler bug, but also just the madness that comes with AnyObject. So the answer is to get rid of it as quickly as you can.

代替此:

for subcontroller in tabBarController.viewControllers! {

您想要这个:

if let viewControllers = tabBarController.viewControllers as? [UIViewController] {
   for subcontroller in viewControllers {

因此,完整的代码是这样的:

So the full code is this:

if let tabBarController = topViewController as? UITabBarController {
    if let viewControllers = tabBarController.viewControllers as? [UIViewController] {
        for subcontroller in viewControllers {
            if let subcontrollerView = subcontroller.view {
                if subcontrollerView.window != nil && subcontroller.isViewLoaded() {
                    topViewController = subcontroller
                    break;
                } } } } }

但是我们可以做得更好.首先,可选链接通常是管理多个if-let的更好方法,当它无法正常工作时,我们可以使用Swift 1.2的新multi-if-let语法来实现这一点:

But we can do better. First, optional chaining is often a better way to manage multiple if-lets, and when it doesn't work well, we can use Swift 1.2's new multi-if-let syntax to get this:

if let tabBarController = topViewController as? UITabBarController,
    viewControllers = tabBarController.viewControllers as? [UIViewController] {
        for subcontroller in viewControllers {
            if subcontroller.view?.window != nil && subcontroller.isViewLoaded() {
                topViewController = subcontroller
                break;
            } } }

这篇关于if-let语句不会解包可选的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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