这个答案就是社区维基。如果您觉得可以做得更好,请随时编辑!
在Swift中,可选
是一种选项类型:它可以包含原始类型(“wrapped”)中的任何值,也可以不包含任何值(特殊值nil
)。在使用可选值之前,必须先展开该值。
Optional是泛型类型,这意味着Optional
和Optional
是不同的类型--<>
中的类型称为包装类型。在下面,可选的是一个枚举,有两种情况:.some(包装的)
和.none
,其中.none
等效于nil
。
var anInt: Int = 42
var anOptionalInt: Int? = 42
var anotherOptionalInt: Int? // `nil` is the default when no value is provided
var aVerboseOptionalInt: Optional<Int> // equivalent to `Int?`
anOptionalInt = nil // now this variable contains nil instead of an integer
Xcode将通过突出显示一行代码来显示崩溃。问题发生在这条线上。
这种崩溃可能发生在两种不同的强制解包下:
这是通过!
运算符在可选的。例如:
let anOptionalString: String?
print(anOptionalString!) // <- CRASH
var optionalDouble: Double! // this value is implicitly unwrapped wherever it's used
print(optionalDouble) // <- CRASH
虽然在某些情况下,您可以使用强制展开,正如您所知道的那样,一个可选项包含一个值,但没有一个地方可以安全地展开该可选项。
这些变量的设计使您可以将它们的赋值推迟到代码的后面。您有责任在访问它们之前确保它们具有价值。但是,因为它们涉及强制展开,所以它们本质上仍然不安全--因为它们假设您的值是非nil,即使指定nil是有效的。
if anOptionalInt != nil {
print("Contains a value!")
} else {
print("Doesn’t contain a value.")
}
例如:
if let number = anOptionalInt {
print("Contains a value! It is \(number)!")
} else {
print("Doesn’t contain a number")
}
它所做的是首先检查可选的是否包含一个值。如果是这样,那么“unwrapped”值被赋给一个新变量(number
)-然后您可以随意使用该变量,就像它是不可选的一样。如果optional不包含值,那么将调用else子句,正如您所期望的那样。
可选绑定的好处是,你可以同时打开多个选项。您可以用逗号分隔语句。如果所有optionals都被打开,该语句将成功。
var anOptionalInt : Int?
var anOptionalString : String?
if let number = anOptionalInt, let text = anOptionalString {
print("anOptionalInt contains a value: \(number). And so does anOptionalString, it’s: \(text)")
} else {
print("One or more of the optionals don’t contain a value")
}
if let number = anOptionalInt, number > 0 {
print("anOptionalInt contains a value: \(number), and it’s greater than zero!")
}
guard let number = anOptionalInt else {
return
}
例如:
guard let number = anOptionalInt else {
return
}
print("anOptionalInt contains a value, and it’s: \(number)!")
Guards还支持if语句支持的相同巧妙技巧,例如同时展开多个optionals和使用WHERE
子句。
是否使用if或guard语句完全取决于将来的代码是否要求可选语句包含值。
let number = anOptionalInt ?? 0
let number = anOptionalInt != nil ? anOptionalInt! : 0
var foo : Foo?
如果我们想在foo
上调用一个不返回任何内容的方法,我们可以简单地执行以下操作:
foo?.doSomethingInteresting()
如果foo
包含一个值,将对其调用此方法。如果不这样做,就不会发生任何不好的事情--代码将继续执行。
(这类似于在Objective-C中向nil
发送消息)
foo?.bar = Bar()
(这是因为对于不返回任何内容的方法,可选值将返回void?
而不是void
)
例如:
if (foo?.bar = Bar()) != nil {
print("bar was set successfully")
} else {
print("bar wasn’t set successfully")
}
然而,当试图访问属性或调用返回值的方法时,事情变得更加棘手。因为foo
是可选的,所以从它返回的任何内容也都是可选的。为了解决这个问题,您可以使用上述方法之一来解压缩返回的optionals,或者在访问方法或调用返回值的方法之前解压缩foo
本身。
let optionalQux = foo?.baz?.qux
let anOptionalString:String?
例如:
var anOptionalString:String? = "bar"
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // Optional("foobar")
但是,如果AnoptionalString
没有值,则map
将返回nil
。例如:
var anOptionalString:String?
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // nil
FlatMap
的工作原理与Map
类似,只是它允许您从闭包正文中返回另一个可选项。这意味着您可以在需要非可选输入的流程中输入可选输入,但本身也可以输出可选输入。
do {
let result = try someThrowingFunc()
} catch {
print(error)
}
do {
let result = try someThrowingFunc()
} catch let error as NSError {
print(error.debugDescription)
}
if let result = try? someThrowingFunc() {
// cool
} else {
// handle the failure, but there's no error information available
}
let result = try! someThrowingFunc()
只有在能够证明其结果在上下文中永远不会失败的情况下,才应该使用try!
--这是非常罕见的。
大多数情况下,您将使用完整的Do-Try-Catch系统-以及可选的try?
,在处理错误并不重要的极少数情况下。
问题内容: 我在Swift 中使用了一个,但是当我尝试更改单元格标签的文本时得到了提示。 有人知道吗? 问题答案: 几乎可以肯定,您的重用标识符不正确。 从方法签名中我们可以看到,返回类型是 Implicitly Unwrapped Optional : 这由以下的感叹号决定: 因此,首先要考虑的是什么是“隐式展开的可选”? Swift编程语言告诉我们: 有时,从程序的结构中可以明显看出,在设置了
我有以下代码: 其名称如下: 但是由于某种原因,我得到了以下错误 致命错误:在展开可选值时意外发现nil 在这一行: 请帮忙调试。 这个问题不同于 “致命错误:在展开可选值时意外发现为零”是什么意思? 这是一个更普遍的问题,与期权的展开有关 此问题特别适用于UIImagePickerController
我在Swift中使用,但当我试图更改单元格标签的文本时,我得到了这个结果。 有人知道这件事吗?
我正在使用来显示来自于一个文件恢复数据库的图像,并且当前得到了错误: 致命错误:在展开可选值时意外发现为零。 不太确定如何执行if检查以防止强制展开,因此如果有人能向我展示另一个语法示例,我将不胜感激。 还尝试将其与nil进行比较(正如文章中所建议的:“致命错误:在展开可选值时意外发现nil”是什么意思?)。
问题内容: 我有下面的这段代码,它在调用keyboardWillShowNotification时运行: 我在第二行看到一条错误消息:。基本上,每当我单击textFields之一时,都会调用该键盘通知,并且其中的代码将运行。我知道我发表了声明,但我想知道为什么我对此一无所获。 我不确定如何收到此错误或如何调试它。是因为我正在模拟器中运行它吗? 这是打印notification.userInfo给出
问题内容: 我正在尝试运行此代码,但我不断收到此错误: 致命错误:解开Optional值时意外发现nil 我不明白这意味着什么或为什么得到它。有什么提示吗? 问题答案: 错误是指以下事实:当可选值设置为nil时,您正在访问可选值的参数(例如,当when 为nil时),这很可能是您的两个之一。 如果该行引发异常,则您为nil。验证是否已成功将其连接到Interface Builder文件中的标签。