Swift:testing可选项为零

我正在使用Xcode 6 Beta 4.我有这种奇怪的情况,我不知道如何适当地testingoptionals。

如果我有一个可选的xyz,是testing的正确方法:

if (xyz) // Do something 

要么

 if (xyz != nil) // Do something 

文件说,这是第一种方式,但我发现,有时,第二种方法是必需的,不会产生编译器错误,但有时,第二种方式会产生编译器错误。

我的具体例子是使用桥接到swift的GData XMLparsing器:

 let xml = GDataXMLDocument( XMLString: responseBody, options: 0, error: &xmlError); if (xmlError != nil) 

在这里,如果我只是这样做:

 if xmlError 

它总是会返回true。 但是,如果我这样做:

 if (xmlError != nil) 

那么它的工作原理(如何在Objective-C中工作)。

GData XML和它对待我缺less的可选项的方法有什么?

在Xcodetesting版5,他们不再让你这样做

 var xyz : NSString? if xyz { //Do Something } 

产生一个错误"does not conform to protocol 'BooleanType.Protocol'"

你必须做这些陈述之一:

 if xyz != nil { //Do Something } if let xy = xyz { //Do Something } 

使用可选项的最直接的方法之一是:

假设xyz是可选types,如Int? 例如。

 if let possXYZ = xyz { // do something with possXYZ (the unwrapped value of xyz) } else { // do something now that we know xyz is .None } 

这样你可以testingxyz包含一个值,如果是的话,立即使用该值。

关于编译器错误, UInt8types不是可选的(注意不是“?”),因此不能转换为nil 。 在对待它之前,确保你正在使用的variables是可选的。

要添加到其他答案中,而不是在if条件中分配一个不同名称的variables:

 var a: Int? = 5 if let b = a { // do something } 

你可以像这样重用相同的variables名称:

 var a: Int? = 5 if let a = a { // do something } 

这可以帮助您避免用完创意variables名称…

这利用了Swift支持的可变阴影 。

从迅速的编程指南

如果陈述和强制解包

您可以使用if语句来确定可选是否包含值。 如果一个可选项有一个值,则它的计算结果为true; 如果它没有任何价值,那么它的评价是错误的。

所以最好的办法是

 // swift > 3 if xyz != nil {} 

如果你在if语句中使用xyz 。那么你可以在常量variables的if语句中解开xyz 。所以你不需要在if语句中使用xyz地方解开每一个地方。

 if let yourConstant = xyz{ //use youtConstant you do not need to unwrap `xyz` } 

这个惯例是由apple提出的,接下来是开发者。

虽然你仍然必须显式比较一个可选的nil或者使用可选的绑定来额外提取它的值(也就是说,可选项并不隐式转换为布尔值),但值得注意的是Swift 2已经添加了guard语句来帮助避免厄运当使用多个可选值时。

换句话说,你的选项现在包括显式检查nil

 if xyz != nil { // Do something with xyz } 

可选绑定:

 if let xyz = xyz { // Do something with xyz // (Note that we can reuse the same variable name) } 

guard声明:

 guard let xyz = xyz else { // Handle failure and then exit this code block // eg by calling return, break, continue, or throw return } // Do something with xyz, which is now guaranteed to be non-nil 

请注意,如果有多个可选值,普通的可选绑定会导致更大的缩进:

 if let abc = abc { if let xyz = xyz { // Do something with abc and xyz } } 

你可以用guard语句来避免这种嵌套:

 guard let abc = abc else { // Handle failure and then exit this code block return } guard let xyz = xyz else { // Handle failure and then exit this code block return } // Do something with abc and xyz 

Swift 3.0,4.0

主要有两种检查可选项的方法。 这里是他们之间比较的例子

如果让

if let是检查可选的最基本的方式为零。 其他条件可以附加到这个零检查,用逗号分隔。 在下一个条件下,variables不能为零。 如果只需要零检查,请删除以下代码中的额外条件。

除此之外,如果x不为零,则将执行if闭包,并且x_val将在内部可用。 否则就会触发else闭包。

 if let x_val = x, x_val > 5 { //x_val available on this scope } else { } 

2.后卫让

guard let可以做类似的事情。 主要目的是使其在逻辑上更合理。 这就像说确保variables不是零,否则停止functionguard let也可以做额外的条件检查。

不同的是,展开后的值将在与guard let相同的范围内可用,如下面的注释所示。 这也导致在其他的closures中,程序必须退出当前范围,通过returnbreak等。

 guard let x_val = x, x_val > 5 else { return } //x_val available on this scope 

而不是if ,当你想要得到一个价值的基础上,三元运算符可能会得心应手:

 func f(x: String?) -> String { return x == nil ? "empty" : "non-empty" } 
 var xyz : NSDictionary? // case 1: xyz = ["1":"one"] // case 2: (empty dictionary) xyz = NSDictionary() // case 3: do nothing if xyz { NSLog("xyz is not nil.") } else { NSLog("xyz is nil.") } 

这个testing在所有情况下都按预期工作。 顺便说一句,你不需要括号()

现在你可以迅速做下面的事情, if nil else事情,你可以重新获得一点目标

 if textfieldDate.text?.isEmpty ?? true { } 

如果你有条件,想打开和比较,如何利用复合布尔expression式的短路评估

 if xyz != nil && xyz! == "some non-nil value" { } 

当然,这不像其他一些build议的post那样可读,但是完成了这个工作,并且比其他build议的解决scheme稍微简洁一些。

除了使用ifguard语句来执行可选绑定之外,另一种方法是使用以下方法扩展Optional

 extension Optional { func ifValue(_ valueHandler: (Wrapped) -> Void) { switch self { case .some(let wrapped): valueHandler(wrapped) default: break } } } 

ifValue接收一个闭包,并在可选参数不为nil时将其作为参数调用。 它是这样使用的:

 var helloString: String? = "Hello, World!" helloString.ifValue { print($0) // prints "Hello, World!" } helloString = nil helloString.ifValue { print($0) // This code never runs } 

你可能应该使用if或者guard因为那些是Swift程序员使用的最传统的方法。