ios Swift:测试 nil 的可选项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/25097727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift: Testing optionals for nil
提问by tng
I'm using Xcode 6 Beta 4. I have this weird situation where I cannot figure out how to appropriately test for optionals.
我正在使用 Xcode 6 Beta 4。我遇到了这种奇怪的情况,我无法弄清楚如何适当地测试可选项。
If I have an optional xyz, is the correct way to test:
如果我有一个可选的 xyz,那么正确的测试方法是:
if (xyz) // Do something
or
或者
if (xyz != nil) // Do something
The documents say to do it the first way, but I've found that sometimes, the second way is required, and doesn't generate a compiler error, but other times, the second way generates a compiler error.
文档说用第一种方式做,但我发现有时需要第二种方式,并且不会产生编译器错误,但有时,第二种方式会产生编译器错误。
My specific example is using the GData XML parser bridged to swift:
我的具体示例是使用桥接到 swift 的 GData XML 解析器:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
Here, if I just did:
在这里,如果我只是这样做:
if xmlError
it would always return true. However, if I do:
它总是会返回 true。但是,如果我这样做:
if (xmlError != nil)
then it works (as how it works in Objective-C).
然后它就可以工作了(就像它在 Objective-C 中的工作方式一样)。
Is there something with the GData XML and the way it treats optionals that I am missing?
GData XML 以及它处理我缺少的选项的方式有什么问题吗?
回答by ktzhang
In Xcode Beta 5, they no longer let you do:
在 Xcode Beta 5 中,它们不再允许您执行以下操作:
var xyz : NSString?
if xyz {
// Do something using `xyz`.
}
This produces an error:
这会产生一个错误:
does not conform to protocol 'BooleanType.Protocol'
不符合协议“BooleanType.Protocol”
You have to use one of these forms:
您必须使用以下形式之一:
if xyz != nil {
// Do something using `xyz`.
}
if let xy = xyz {
// Do something using `xy`.
}
回答by zevij
To add to the other answers, instead of assigning to a differently named variable inside of an if
condition:
要添加到其他答案中,而不是在if
条件内分配给不同名称的变量:
var a: Int? = 5
if let b = a {
// do something
}
you can reuse the same variable name like this:
您可以像这样重用相同的变量名:
var a: Int? = 5
if let a = a {
// do something
}
This might help you avoid running out of creative variable names...
这可能会帮助您避免用完创意变量名称...
This takes advantage of variable shadowingthat is supported in Swift.
这利用了Swift 支持的变量阴影。
回答by Isaac Drachman
One of the most direct ways to use optionals is the following:
使用选项的最直接方法之一如下:
Assuming xyz
is of optional type, like Int?
for example.
假设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
}
This way you can both test if xyz
contains a value and if so, immediately work with that value.
通过这种方式,您可以测试是否xyz
包含一个值,如果包含,则立即使用该值。
With regards to your compiler error, the type UInt8
is not optional (note no '?') and therefore cannot be converted to nil
. Make sure the variable you're working with is an optional before you treat it like one.
关于您的编译器错误,该类型UInt8
不是可选的(注意没有“?”),因此无法转换为nil
. 在将其视为一个变量之前,请确保您正在使用的变量是一个可选变量。
回答by Fangming
Swift 3.0, 4.0
斯威夫特 3.0、4.0
There are mainly two ways of checking optional for nil. Here are examples with comparison between them
主要有两种方式检查 optional 是否为 nil。以下是它们之间的比较示例
1. if let
1.如果让
if let
is the most basic way to check optional for nil. Other conditions can be appended to this nil check, separated by comma. The variable must not be nil to move for the next condition. If only nil check is required, remove extra conditions in the following code.
if let
是检查 optional 为 nil 的最基本方法。其他条件可以附加到此 nil 检查中,以逗号分隔。变量不能为 nil 以移动到下一个条件。如果只需要 nil 检查,请删除以下代码中的额外条件。
Other than that, if x
is not nil, the if closure will be executed and x_val
will be available inside. Otherwise the else closure is triggered.
除此之外,如果x
不是 nil,则 if 闭包将被执行并x_val
在内部可用。否则触发 else 闭包。
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
2. guard let
2.守护让
guard let
can do similar things. It's main purpose is to make it logically more reasonable. It's like saying Make sure the variable is not nil, otherwise stop the function. guard let
can also do extra condition checking as if let
.
guard let
可以做类似的事情。它的主要目的是使其在逻辑上更合理。这就像说确保变量不为零,否则停止函数。guard let
也可以做额外的条件检查if let
。
The differences are that the unwrapped value will be available on same scope as guard let
, as shown in the comment below. This also leads to the point that in else closure, the program has to exit the current scope, by return
, break
, etc.
不同之处在于解包的值将在与 相同的范围内可用guard let
,如下面的评论所示。这也导致在其他封闭,该程序必须退出当前范围来看,通过return
,break
等等。
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
回答by codester
From swift programming guide
来自 swift 编程指南
If Statements and Forced Unwrapping
You can use an if statement to find out whether an optional contains a value. If an optional does have a value, it evaluates to true; if it has no value at all, it evaluates to false.
If 语句和强制解包
您可以使用 if 语句来确定一个可选项是否包含一个值。如果一个可选项确实有一个值,它的计算结果为真;如果它根本没有价值,则评估为假。
So the best way to do this is
所以最好的方法是
// swift > 3
if xyz != nil {}
and if you are using the xyz
in if statement.Than you can unwrap xyz
in if statement in constant variable .So you do not need to unwrap every place in if statement where xyz
is used.
并且如果您使用xyz
in if 语句。那么您可以xyz
在常量变量中的 if 语句中解包。因此,您不需要解包 if 语句中xyz
使用的每个地方。
if let yourConstant = xyz{
//use youtConstant you do not need to unwrap `xyz`
}
This convention is suggested by apple
and it will be followed by devlopers.
这个约定是由开发人员建议的,apple
并且会被开发人员遵循。
回答by Chris Frederick
Although you must still either explicitly compare an optional with nil
or use optional binding to additionally extract its value (i.e. optionals are not implicitly converted into Boolean values), it's worth noting that Swift 2 has added the guard
statementto help avoid the pyramid of doomwhen working with multiple optional values.
尽管您仍然必须显式地将可选项与nil
或使用可选项绑定来额外提取其值(即选项不会隐式转换为布尔值),但值得注意的是,Swift 2 已添加该guard
语句以帮助避免工作时出现厄运金字塔具有多个可选值。
In other words, your options now include explicitly checking for nil
:
换句话说,您现在的选择包括明确检查nil
:
if xyz != nil {
// Do something with xyz
}
Optional binding:
可选绑定:
if let xyz = xyz {
// Do something with xyz
// (Note that we can reuse the same variable name)
}
And guard
statements:
和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
Note how ordinary optional binding can lead to greater indentation when there is more than one optional value:
请注意,当有多个可选值时,普通的可选绑定如何导致更大的缩进:
if let abc = abc {
if let xyz = xyz {
// Do something with abc and xyz
}
}
You can avoid this nesting with guard
statements:
您可以使用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
回答by Brody Robertson
Swift 5 Protocol Extension
Swift 5 协议扩展
Here is an approach using protocol extension so that you can easily inline an optional nil check:
这是一种使用协议扩展的方法,以便您可以轻松内联可选的 nil 检查:
import Foundation
public extension Optional {
var isNil: Bool {
guard case Optional.none = self else {
return false
}
return true
}
var isSome: Bool {
return !self.isNil
}
}
Usage
用法
var myValue: String?
if myValue.isNil {
// do something
}
if myValue.isSome {
// do something
}
回答by Tiago
Another approach besides using if
or guard
statements to do the optional binding is to extend Optional
with:
除了使用if
orguard
语句进行可选绑定之外,另一种方法是扩展Optional
:
extension Optional {
func ifValue(_ valueHandler: (Wrapped) -> Void) {
switch self {
case .some(let wrapped): valueHandler(wrapped)
default: break
}
}
}
ifValue
receives a closure and calls it with the value as an argument when the optional is not nil. It is used this way:
ifValue
接收一个闭包并在可选值不为 nil 时使用该值作为参数调用它。它是这样使用的:
var helloString: String? = "Hello, World!"
helloString.ifValue {
print(if let _ = xyz {
// something that should only happen if xyz is not nil
}
) // prints "Hello, World!"
}
helloString = nil
helloString.ifValue {
print(func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
) // This code never runs
}
You should probably use an if
or guard
however as those are the most conventional (thus familiar) approaches used by Swift programmers.
您可能应该使用if
or ,guard
因为它们是 Swift 程序员使用的最传统(因此很熟悉)的方法。
回答by Ben Lachman
One option that hasn't specifically been covered is using Swift's ignored value syntax:
一个没有特别提及的选项是使用 Swift 的忽略值语法:
##代码##I like this since checking for nil
feels out of place in a modern language like Swift. I think the reason it feels out of place is that nil
is basically a sentinel value. We've done away with sentinels pretty much everywhere else in modern programming so nil
feels like it should go too.
我喜欢这个,因为nil
在像 Swift 这样的现代语言中检查感觉不合适。我认为它感觉不合适的原因nil
基本上是一个哨兵值。在现代编程中,我们几乎在所有其他地方都取消了哨兵,所以nil
感觉也应该这样做。
回答by qed
Instead of if
, ternary operator might come handy when you want to get a value based on whether something is nil:
相反的if
,当你要根据东西是否是零得到一个值三元运营商可能来方便: