使用带逻辑 AND 操作符 & & 的 Swift

我们知道我们可以使用 if let语句作为速记来检查可选的 nil 然后展开。

但是,我想使用逻辑 AND 操作符 &&将它与另一个表达式组合在一起。

因此,例如,在这里我做了可选的链接来展开并可选地将 rootViewController 下调到 tabBarController。但是,我不想使用嵌套的 if 语句,而是将它们组合在一起。

if let tabBarController = window!.rootViewController as? UITabBarController {
if tabBarController.viewControllers.count > 0 {
println("do stuff")
}
}

综合捐赠:

if let tabBarController = window!.rootViewController as? UITabBarController &&
tabBarController.viewControllers.count > 0 {
println("do stuff")
}
}

上面给出了编译错误 使用未解析的标识符‘ tabBarController’

简化:

if let tabBarController = window!.rootViewController as? UITabBarController && true {
println("do stuff")
}

这将产生一个编译错误 条件绑定中的绑定值必须是可选类型。在尝试了各种语法变化之后,每种变化都会产生不同的编译器错误。我还没有找到顺序和括号的最佳组合。

所以,问题是,这可能吗? 如果可能的话,正确的语法是什么?

注意,我想用一个 if语句 没有一个 switch语句或一个三元 ?操作符来完成这个操作。

48097 次浏览

It is not possible.

From Swift grammar

GRAMMAR OF AN IF STATEMENT

if-statement → if ­if-condition­ code-block­ else-clause­opt­

if-condition → expression­ | declaration­

else-clause → else­ code-block­ | else­ if-statement­

The value of any condition in an if statement must have a type that conforms to the BooleanType protocol. The condition can also be an optional binding declaration, as discussed in Optional Binding

if-condition must be expression­ or declaration­. You can't have both expression and declaration.

let foo = bar is a declaration, it doesn't evaluate to a value that conforms to BooleanType. It declares a constant/variable foo.

Your original solution is good enough, it is much more readable then combining the conditions.

As of Swift 1.2, this is now possible. The Swift 1.2 and Xcode 6.3 beta release notes state:

More powerful optional unwrapping with if let — The if let construct can now unwrap multiple optionals at once, as well as include intervening boolean conditions. This lets you express conditional control flow without unnecessary nesting.

With the statement above, the syntax would then be:

if let tabBarController = window!.rootViewController as? UITabBarController where tabBarController.viewControllers.count > 0 {
println("do stuff")
}

This uses the where clause.

Another example, this time casting AnyObject to Int, unwrapping the optional, and checking that the unwrapped optional meets the condition:

if let w = width as? Int where w < 500
{
println("success!")
}

For those now using Swift 3, "where" has been replaced by a comma. The equivalent would therefore be:

if let w = width as? Int, w < 500
{
println("success!")
}

Max's answer is correct and one way of doing this. Notice though that when written this way:

if let a = someOptional where someBool { }

The someOptional expression will be resolved first. If it fails then the someBool expression will not be evaluated (short-circuit evaluation, as you'd expect).

If you want to write this the other way around it can be done like so:

if someBool, let a = someOptional { }

In this case someBool is evaluated first, and only if it evaluates to true is the someOptional expression evaluated.

In Swift 3 Max MacLeod's example would look like this:

if let tabBarController = window!.rootViewController as? UITabBarController, tabBarController.viewControllers.count > 0 {
println("do stuff")
}

The where was replaced by ,

Swift 4, I will use,

let i = navigationController?.viewControllers.index(of: self)
if let index = i, index > 0, let parent = navigationController?.viewControllers[index-1] {
// access parent
}
if let tabBarController = window!.rootViewController as? UITabBarController ,
tabBarController.viewControllers?.count ?? 0 > 0 {
println("do stuff")
}
}