if-let语句不打开可选

我在我的代码中碰到了一些似乎好奇的东西,并且想知道这个行为是否有一个简单的解释。 鉴于以下声明:

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代码控制台返回以下内容:

 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常量是一样的。 为什么?

你的问题是AnyObject 。 (如果有疑问,你的问题总是AnyObject ;这是一个应该尽可能避免的恶意types,唯一更糟的是AnyObject?

问题是[AnyObject]?返回[AnyObject]? ,可选的促销可能会导致事情横向。 这很可能会推动一个AnyObject?AnyObject?? 然后变得困惑。 这是一个编译器错误,也是AnyObject自带的疯狂。 所以答案是尽可能快地摆脱它。

而不是这个:

 for subcontroller in tabBarController.viewControllers! { 

你要这个:

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

所以完整的代码是这样的:

 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; } } } } } 

但是我们可以做得更好。 首先,可选的链接通常是更好的pipe理多个if-let的方法,当它不能正常工作时,我们可以使用Swift 1.2的新的多if-let语法来获得这个:

 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; } } }