swift可选类型
Swift Optional is a very important underlying concept in Swift programming. Optional is something that you’d be dealing a lot in Swift development. Let’s see what it has in-store for us. If you aren’t aware of the basics of Swift, you can breeze through this article before proceeding.
Swift Optional是Swift编程中非常重要的基础概念。 可选是在Swift开发中要处理的很多事情。 让我们看看它为我们提供了什么。 如果你不知道斯威夫特的基础知识,您可以通过微风此文章,然后再继续。
Typically in Swift we define a variable or constant as:
通常,在Swift中,我们将变量或常量定义为:
var str = "String type inferred"
var string:String = "Type defined"
let const = "I'm a constant. I can't change"
let i:Int = 0
Note: let constants can’t be changed once defined.
注意 :一旦定义,就不能更改常量。
It’s all good with the above declarations until we try setting it as below.
上面的声明都很好,直到我们尝试如下设置为止。
string = nil //Compile Time Error: error: nil cannot be assigned to type 'String'
var currentValue:String = nil //Error
The above snippet shows that Swift variables, constants always require a value. Setting no value would lead to compile-time error. This is where Swift gives us Optional, a very powerful feature. We can use optional in situations where a value may be absent (like storing nil values in the above snippet).
上面的代码片段显示了Swift变量,常量始终需要一个值。 不设置任何值将导致编译时错误。 这就是Swift为我们提供Optional(一项非常强大的功能)的地方。 我们可以在可能不存在值的情况下使用可选(例如,在上面的代码段中存储nil值)。
Swift Optional variable or constant can contain a value or a nil value. An optional variable/constant declaration requires a ?
after the type. A declaration of an optional variable/constant is given below.
Swift可选变量或常量可以包含值或nil值。 可选的变量/常量声明需要一个?
类型之后。 下面给出了可选变量/常量的声明。
var currentValue:Int? = nil
var x :String? = "Optional variable"
print(currentValue) //prints nil
print(x) //prints Optional("Optional variable")
currentValue = 1
x = nil
print(currentValue)//prints Optional(1)
print(x) //prints nil
Swift Optionals are just a type like normal types. Optional types act as a wrapper over the normal types with the added functionality to allow the variable/constant to be nil.
斯威夫特选配就像普通类型的一个类型 。 可选类型充当普通类型的包装 ,并具有添加的功能,以允许变量/常量为nil 。
Hence printing an optional would wrap the value inside Optional()
.
因此,打印一个可选的将包装价值在Optional()
。
Any optional type Int?
or String?
is not the same as Int
or String
. Therefore an Optional type cannot interact with a normal type. Neither can an optional type interact with another optional type as shown in the below image.
有可选的Int?
类型Int?
或String?
与Int
或String
。 因此,可选类型不能与普通类型进行交互。 可选类型不能与另一可选类型交互,如下图所示。
To use the value of an Optional type we need to unwrap it using !
. That’s what XCode recommends. But is it ideal? We’ll see all this shortly.
要使用Optional类型的值,我们需要使用!
。 这就是XCode的建议。 但是理想吗? 我们很快就会看到所有这些。
Swift Optional variable unwrapping is used to convert an optional type to a normal type (Int? to Int).
Swift可选变量解包用于将可选类型转换为普通类型(从Int?到Int)。
There are two types of unwrapping:
展开有两种类型:
This is what XCode suggests (check previous image) by adding a !
at the end of optional variable. An example is given below.
这就是XCode通过添加!
建议的内容(检查上一张图像) !
在可选变量的末尾。 下面给出一个例子。
var a:Int? = 2
var c:Int? = 3
var b:Int = 4
print(a!) // prints 2
print(a! + b) //prints 6
print(a! + c!) //prints 5
var unwrapThis:String? = "Unwrap me please"
print(unwrapThis) //prints Optional("Unwrap me please")
print(unwrapThis!)//prints Unwrap me please
It can get pretty redundant while adding a !
to each optional variable/constant.
添加!
它可能会变得非常多余!
每个可选变量/常量。
We can define an optional variable that’ll implicitly unwrap when called as shown below.
我们可以定义一个可选变量,该变量在调用时将隐式解包,如下所示。
var a:Int! = 2
var c:Int! = 3
var b:Int = 4
print(a) // prints 2
print(a + b) //prints 6
print(a + c) //prints 5
A variable with !
instead of ?
after the type is known as Implicitly Unwrapped Optional. This would be able to interact with normal variables whenever called since it’ll be implicitly unwrapped to a normal type.
有变量!
代替?
类型称为隐式展开后可选 。 每当调用它时,它就可以与普通变量进行交互,因为它将隐式地展开为普通类型。
Good to know, but defining this way can be risky when the variable/constant is nil (it’ll cause a crash since normal type can’t have a nil value).
众所周知,但是当变量/常量为nil时定义这种方式可能会很冒险(因为普通类型不能具有nil值,所以会导致崩溃)。
It’s noteworthy to mention that Force Unwrapping tells the Swift compiler that you’re sure that the variable won’t be nil. This can’t always be the case. This is where the second type of unwrapping comes to the rescue.
值得注意的是,Force Unwrapping告诉Swift编译器您确定变量不会为nil。 并非总是如此。 这是救援的第二种类型。
Here we conditionally check if the optional variable has a nil value or not. Only if it doesn’t have we’ll unwrap it. One way to unwrap an optional is to check if the value is nil before force unwrapping as shown below.
在这里,我们有条件地检查可选变量是否具有nil值。 仅当它没有时,我们才会对其进行包装。 展开可选内容的一种方法是在强制展开之前检查该值是否为nil,如下所示。
if name != nil
{
if desc != nil
{
print(name! + ": " + desc!) //prints Swift Tutorial: Optionals
}
else{
print(name! + ": Undefined")
}
}
else{
print("Nothing is defined")
}
In the above approach, we’ll only unwrap when we’re sure the value is not nil.
在上述方法中,只有在确定值不为nil时,我们才会解开包装。
Note: Swift compiler is sensitive to white spacing.
注意:Swift编译器对白色间距敏感。
Optional unwrapping using ternary operator is given below.
下面给出了使用三元运算符的可选解包。
var i:Int? = nil
let ternary = i != nil ? i! : -1
print("Value of i is \(ternary)") //prints -1
Swift has an even clever approach to unwrap an optional. Let’s see that in the next section.
Swift甚至有一个巧妙的方法来解开一个可选的东西。 让我们在下一部分中看到它。
Swift Optional Binding is used to find out whether an optional contains a value or not. If it does then make that value available as a temporary constant or variable. All this is performed in a single action. An example is given below.
Swift Optional Binding用于查找可选项是否包含值。 如果确实如此,则将该值用作临时常量或变量。 所有这一切都在一个动作中完成。 下面给出一个例子。
var desc: String? = "Optionals"
if let temp = desc{
print(temp)
}
else{
print("No description")
}
In the above code, if the value inside desc
is not nil we save it in a temporary variable or constant and use it.
Optional binding is the recommended way to unwrap an optional.
在上面的代码中,如果desc
的值不是nil,我们将其保存在一个临时变量或常量中并使用它。
建议使用可选绑定来解开可选 。
An example using multiple if let is given below.
下面给出了一个使用多个if let的示例。
var first:String? = "first"
var second:String? = "second"
var third:String? = "third"
if let f = first {
if let s = second{
if let t = third{
print(f + " " + s + " " + t )
}
else{
print(f + " " + s + " NA")
}
}
else{
print(f + " NA")
}
}
else{
print("NA")
}
Now, this has too much of nesting and would require too many if-let checks so that the temporary variables are available in each scope. Surely we can improve it.
现在,它具有太多的嵌套,将需要太多的if-let检查,以便每个范围中都可以使用临时变量。 当然,我们可以改善它。
There’s a super short form to do an optional binding if-let
as shown below.
有一个超短格式可以执行可选的if-let
绑定,如下所示。
var first:String? = "first"
var second:String? = nil
let f = first ?? "NA"
print(f) //prints first
let s = second ?? "NA"
print(s) //prints NA
The ??
unwraps and stores the optional value in the variable/constant. If the optional value is nil
, it uses the default value present on the right hand side.
??
将可选值解包并将其存储在变量/常量中。 如果可选值为nil
,则使用右侧的默认值。
The above concept can be applied to the nested if let
code shown previously.
if let
代码显示,上述概念可以应用于嵌套。
var first:String? = "first"
var second:String? = nil
var third:String? = "third"
print ("\(first ?? "NA")" + " \(second ?? "NA")" + " \(third ?? "NA")") // prints first NA third
We can unwrap multiple optionals in a single if statement separated by commas as shown below:
我们可以在单个if语句中用逗号分隔多个可选选项,如下所示:
var optionalX :String? = "x"
var optionalY :String? = "y"
if let x = optionalX, let y = optionalY
{
print(x) //prints "x"
print(y) //prints"y"
}
else{
print("One or more Optional can't be unwrapped")
}
However there’s one pitfall in the above approach. If any of the optionals can’t be unwrapped, none of them can be used in the if statement as shown below:
但是,上述方法存在一个陷阱。 如果任何可选选项都无法解包,则不能在if语句中使用它们,如下所示:
var optionalX :String? = "x"
var optionalY :String? = "y"
var optionalZ :String?
if let x = optionalX, let y = optionalY, let z = optionalZ
{
print(x)
print(y)
print(z)
}
else{
print("One or more Optional can't be unwrapped") //this gets printed. x and y are skipped too.
}
Hence the above approach is recommended only when you need the values from all optionals or none.
因此,仅当您需要所有可选值中的任何一个或都不使用任何可选值时,才建议使用上述方法。
guard is another powerful feature in Swift that can be used in place of nested if let
.
guard是Swift中的另一个强大功能,可以if let
代替嵌套。
guard is similar to if condition except the fact that guard checks for all the bad cases only. The structure of a guard statement is in the form:
警卫与if条件类似,只是警卫仅检查所有不良情况。 保护声明的结构形式为:
func functionName()
{
guard else{ //break or return since the condition has failed }
//Do something since your condition has passed the bad checks.
}
A guard is in a way an inverted if condition. Besides guard works only inside functions. An example of guard is given below.
警卫在某种程度上是一种颠倒的条件。 此外,guard仅在功能内部起作用。 下面给出了一个防护示例。
func exampleGuard() {
var didWeMeet = false
guard !didWeMeet else { return }
print("Did we meet? " + String(didWeMeet))
}
exampleGuard() //prints "Did we meet? false\n"
//Example 2
func exampleGuard2() {
var didWeMeet = false
guard didWeMeet else { return }
print("Did we meet? " + String(didWeMeet))
}
exampleGuard2() //else statement executed and function returns void
In the above code if the condition entered after guard keyword fails the function would execute the else case and return. An example of guard with optional binding is given below:
在上面的代码中,如果在guard关键字之后输入的条件失败,则该函数将执行else情况并返回。 下面给出了带有可选绑定的后卫示例:
var second:String? = nil
func guardStatements()
{
guard let sa = second else{
print("nil value")
return
}
print(sa)
}
guardStatements() //prints nil value
In the above code since the optional value of second is nil, the else statement of the guard runs and the function exits there itself.
在上面的代码中,由于second的可选值是nil,所以将运行guard的else语句,并且函数本身会在那里退出。
If the value was successfully unwrapped the print(sa) statement would have run.
如果成功解开该值,则print(sa)语句将运行。
Let’s finally convert the nested if let statements into guard statements and see how easily we can get rid of nested conditions.
最后,让我们将嵌套的if语句转换为保护语句,看看我们如何轻松摆脱嵌套条件。
func guardStatements()
{
guard let f = first else{
print("nil value")
return
}
guard let s = second else{
print("nil value")
return
}
guard let t = third else{
print("nil value")
return
}
print(f + " " + s + " " + t)
}
guardStatements() //prints first second third
// Isn't the above code simpler than the below one?
var first:String? = "first"
var second:String? = "second"
var third:String? = "third"
if let f = first {
if let s = second{
if let t = third{
print(f + " " + s + " " + t )
}
else{
print(f + " " + s + " NA")
}
}
else{
print(f + " NA")
}
}
else{
print("NA")
}
Swift guard checks for bad cases only. If in any of the guard let
, the condition (bad case) is met, the function would exit there itself.
迅捷守卫只检查不良情况。 如果在任何一个guard let
,条件(坏情况)都得到满足,则函数将自行退出。
Note: Difference between guard let and if let
注意 : 后卫让位和如果让位之间的区别
Hence guard let is preferred over if let!
因此后卫让优于如果再让 !
This brings an end Swift Optional tutorial.
这样就结束了Swift可选教程。
翻译自: https://www.journaldev.com/15208/swift-optional
swift可选类型