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不是零,否则停止function 。  guard let也可以做额外的条件检查。 
 不同的是,展开后的值将在与guard let相同的范围内可用,如下面的注释所示。 这也导致在其他的closures中,程序必须退出当前范围,通过return , break等。 
 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稍微简洁一些。
 除了使用if或guard语句来执行可选绑定之外,另一种方法是使用以下方法扩展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程序员使用的最传统的方法。