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语句应该为我打开条件 – 但这不是这里展示的行为。 我不能访问subcontrollerView
的window
属性,除非我再次解包可选。 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; } } }