我正在使用Xcode 6 Beta 4.我有这种奇怪的情况,我无法弄清楚如何正确测试选项。
如果我有一个可选的xyz,是正确的测试方法:
if (xyz) // Do something
或
if (xyz != nil) // Do something
文档说这是第一种方式,但我发现有时,第二种方式是必需的,并且不会产生编译错误,但有时,第二种方式生成编译器错误。
我的具体示例是使用桥接到swift的GData XML解析器:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
在这里,如果我刚刚做了:
if xmlError
它总是会返回true。但是,如果我这样做:
if (xmlError != nil)
然后它起作用(如在Objective-C中如何工作)。
是否存在GData XML的某些内容以及它对待我缺少的选项的方式?
答案 0 :(得分:142)
在Xcode Beta 5中,他们不再允许你这样做:
var xyz : NSString?
if xyz {
// Do something using `xyz`.
}
这会产生错误:
不符合协议' BooleanType.Protocol'
您必须使用以下表格之一:
if xyz != nil {
// Do something using `xyz`.
}
if let xy = xyz {
// Do something using `xy`.
}
答案 1 :(得分:19)
要添加到其他答案,而不是在if
条件内分配不同命名的变量:
var a: Int? = 5
if let b = a {
// do something
}
您可以重复使用相同的变量名称:
var a: Int? = 5
if let a = a {
// do something
}
这可以帮助您避免耗尽广告素材变量名称...
这利用了Swift支持的variable shadowing。
答案 2 :(得分:18)
使用选项的最直接方法之一是:
假设xyz
属于可选类型,例如Int?
。
if let possXYZ = xyz {
// do something with possXYZ (the unwrapped value of xyz)
} else {
// do something now that we know xyz is .None
}
通过这种方式,您可以测试xyz
是否包含值,如果是,则立即使用该值。
关于编译器错误,UInt8
类型不是可选的(注意没有'?')因此无法转换为nil
。在您将其视为一个变量之前,请确保您正在使用的变量是可选的。
答案 3 :(得分:13)
Swift 3.0,4.0
主要有两种方法可以检查nil的可选项。以下是它们之间进行比较的例子
<强> 1。如果让
if let
是检查nil可选项的最基本方法。其他条件可以附加到此nil检查,以逗号分隔。对于下一个条件,变量不能为nil。如果只需要nil检查,请删除以下代码中的额外条件。
除此之外,如果x
不是nil,则将执行if闭包,并且x_val
将在其中可用。否则会触发else闭包。
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
<强> 2。警卫让
guard let
可以做类似的事情。它的主要目的是使其在逻辑上更合理。这就像说确保变量不是nil,否则停止功能。 guard let
也可以将额外的条件检查设为if let
。
不同之处在于,展开的值将与guard let
在同一范围内可用,如下面的注释所示。这也导致了在else闭包中,程序必须退出当前范围,return
,break
等。
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
答案 4 :(得分:10)
来自swift编程guide
如果语句和强制解包
您可以使用if语句来确定可选项是否包含 值。如果可选项具有值,则计算结果为true;如果它 没有任何价值,它的评估结果为假。
所以最好的方法是
// swift > 3
if xyz != nil {}
如果您在if语句中使用xyz
。那么您可以在常量变量中的if语句中展开xyz
。因此,您不需要在if语句中展开{{1使用。
xyz
此约定由if let yourConstant = xyz{
//use youtConstant you do not need to unwrap `xyz`
}
建议,然后是devlopers。
答案 5 :(得分:8)
虽然您仍然必须明确地将可选项与nil
进行比较,或者使用可选绑定来另外提取其值(即,选项不会隐式转换为布尔值),但值得注意的是Swift 2添加了{{ 3}}在处理多个可选值时帮助避免使用guard
statement。
换句话说,您的选项现在包括明确检查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
// e.g. 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
答案 6 :(得分:3)
而不是if
,当你想根据某些东西是否为零来获取值时,三元运算符可能会派上用场:
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
答案 7 :(得分:2)
除了使用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程序员使用的最常规(熟悉)方法。
答案 8 :(得分:1)
一个尚未明确涵盖的选项是使用Swift的被忽略值语法:
if let _ = xyz {
// something that should only happen if xyz is not nil
}
我之所以喜欢这样,是因为检查nil
在像Swift这样的现代语言中感觉不合适。我认为感觉不合时宜的原因是nil
基本上是哨兵值。在现代编程中,我们几乎已经无处使用哨兵了,所以nil
感觉也应该去。
答案 9 :(得分:1)
Swift 5协议扩展
这是一种使用协议扩展的方法,因此您可以轻松地内联可选的nil检查:
public extension Optional {
var isNil: Bool {
guard case Optional.none = self else {
return false
}
return true
}
}
用法
var myValue: String?
if !myValue.isNil {
// do something
}
答案 10 :(得分:0)
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.") }
此测试在所有情况下都按预期工作。
顺便说一句,您不需要括号()
。
答案 11 :(得分:0)
现在你可以迅速做下面的事情,让你重新获得一点目标-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
答案 12 :(得分:0)
如果您有条件且想要打开并进行比较,那么如何利用复合布尔表达式的短路评估,如
if xyz != nil && xyz! == "some non-nil value" {
}
当然,这不像其他一些建议的帖子那样可读,但是比其他建议的解决方案完成工作并且有些简洁。
答案 13 :(得分:0)
您还可以使用Nil-Coalescing Operator
如果
nil-coalescing operator
(a ?? b
)包含可选的a
值,则解开可选的a
;如果{ {1}}是a
。表达式a始终是可选类型。表达式b
必须与a
内部存储的类型匹配。
nil
如果b
是a
,它将自动为let value = nullableValue ?? defaultValue
赋值