Swift 什么是;致命错误:在展开可选值“时意外发现nil”;什么意思?
我的Swift程序因Swift 什么是;致命错误:在展开可选值“时意外发现nil”;什么意思?,swift,exception,error-handling,Swift,Exception,Error Handling,我的Swift程序因EXC\u BAD\u指令和以下类似错误之一而崩溃。这个错误是什么意思?我该如何修复它 致命错误:在展开可选值时意外发现nil 或 致命错误:隐式展开可选值时意外发现nil 这篇文章旨在收集“意外发现零”问题的答案,这样它们就不会分散和难以找到。请随意添加您自己的答案或现有的wiki答案。此答案是。如果你觉得可以做得更好,请随意 背景:什么是可选的? 在Swift中,是一个:它可以包含原始(“包装”)类型中的任何值,或者根本不包含任何值(特殊值nil)。可选值必须是展开的,
EXC\u BAD\u指令
和以下类似错误之一而崩溃。这个错误是什么意思?我该如何修复它
致命错误:在展开可选值时意外发现nil
或
致命错误:隐式展开可选值时意外发现nil
这篇文章旨在收集“意外发现零”问题的答案,这样它们就不会分散和难以找到。请随意添加您自己的答案或现有的wiki答案。此答案是。如果你觉得可以做得更好,请随意 背景:什么是可选的? 在Swift中,是一个:它可以包含原始(“包装”)类型中的任何值,或者根本不包含任何值(特殊值
nil
)。可选值必须是展开的,才能使用
Optional是a,这意味着Optional
和Optional
是不同的类型,
中的类型称为包装类型。在发动机罩下,可选的是一个带有两个箱子的箱子:。一些(包装)
和。无
,其中。无
相当于无
if anOptionalInt != nil {
print("Contains a value!")
} else {
print("Doesn’t contain a value.")
}
Optionals可以使用命名类型Optional
,或者(最常见的)作为带有?
后缀的速记来声明
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
致命错误:在展开可选值时意外发现nil
由于此处的anOptionalString
为nil
,您将在强制展开该字符串的行上发生崩溃
2.隐式展开选项
这些是用定义的代码>,而不是类型后面的?
var optionalDouble: Double! // this value is implicitly unwrapped wherever it's used
假设这些选项包含一个值。因此,每当您访问隐式展开的可选项时,它将自动为您强制展开。如果它不包含值,它将崩溃
print(optionalDouble) // <- CRASH
然而,99.9%的时间在使用optionals时,如果它包含一个值,您实际上会想要访问它包含的值。为此,可以使用可选绑定
可选绑定
可选绑定允许您检查可选绑定是否包含值,并允许您将未包装的值分配给新变量或常量。它使用语法if let x=anOptional{…}
或if var x=anOptional{…}
,具体取决于绑定后是否需要修改新变量的值
例如:
let anOptionalString: String?
print(anOptionalString!) // <- CRASH
if let number = anOptionalInt {
print("Contains a value! It is \(number)!")
} else {
print("Doesn’t contain a number")
}
guard let number = anOptionalInt else {
return
}
print("anOptionalInt contains a value, and it’s: \(number)!")
foo?.bar = Bar()
if (foo?.bar = Bar()) != nil {
print("bar was set successfully")
} else {
print("bar wasn’t set successfully")
}
var anOptionalString:String? = "bar"
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // Optional("foobar")
var anOptionalString:String?
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // nil
do {
let result = try someThrowingFunc()
} catch let error as NSError {
print(error.debugDescription)
}
这样做的目的是首先检查可选项是否包含值。如果是,则将“unwrapped”值指定给一个新变量(number
)——您可以像非可选变量一样自由使用该变量。如果optional不包含值,那么将调用else子句,正如您所期望的那样
可选绑定的好处在于,您可以同时打开多个可选绑定。您可以用逗号分隔这些语句。如果所有选项都已展开,则该语句将成功
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!")
}
在if语句中使用可选绑定的唯一缺点是,只能从语句范围内访问未包装的值。如果需要从语句范围之外访问该值,可以使用guard语句
允许您定义成功的条件,并且当前作用域只有在满足该条件时才会继续执行。它们是用语法guard condition else{…}
定义的
因此,要将它们与可选绑定一起使用,可以执行以下操作:
guard let number = anOptionalInt else {
return
}
(请注意,在防护体中,您必须使用其中一个以退出当前执行代码的范围)
如果anOptionalInt
包含一个值,它将被展开并分配给新的number
常量。保护之后的代码将继续执行。如果它不包含值–警卫将执行括号内的代码,这将导致控制权的转移,因此紧随其后的代码将不会执行
guard语句真正巧妙的地方在于,现在可以在语句后面的代码中使用unwrapped值(正如我们所知,未来的代码只能在可选值有值的情况下执行)。这对于消除嵌套多个if语句所创建的错误非常有用
例如:
let anOptionalString: String?
print(anOptionalString!) // <- CRASH
if let number = anOptionalInt {
print("Contains a value! It is \(number)!")
} else {
print("Doesn’t contain a number")
}
guard let number = anOptionalInt else {
return
}
print("anOptionalInt contains a value, and it’s: \(number)!")
foo?.bar = Bar()
if (foo?.bar = Bar()) != nil {
print("bar was set successfully")
} else {
print("bar wasn’t set successfully")
}
var anOptionalString:String? = "bar"
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // Optional("foobar")
var anOptionalString:String?
anOptionalString = anOptionalString.map {unwrappedString in
return "foo".stringByAppendingString(unwrappedString)
}
print(anOptionalString) // nil
do {
let result = try someThrowingFunc()
} catch let error as NSError {
print(error.debugDescription)
}
Guards还支持与if语句支持的相同的整洁技巧,例如同时展开多个选项并使用where
子句
是否使用if或guard语句完全取决于将来的代码是否要求optional包含值
零凝聚算子
是的一个漂亮的速记版本,主要用于将可选项转换为非可选项。它的语法是a??b
,其中a
为可选类型,b
与a
为同一类型(尽管通常为非可选)
它基本上允许您说“如果a
包含一个值,则将其展开。如果它不包含值,则返回b
”。例如,您可以这样使用它:
let number = anOptionalInt ?? 0
let newFoo = foo ?? "nil" // "??" is the nil coalescing operator
print("foo = \(newFoo)")
if let nameOfDaughter = nameOfDaughter {
print("My daughters name is: \(nameOfDaughter)")
}
guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")
这将定义一个Int
类型的number
常量,该常量将包含anOptionalInt
的值(如果它包含值),否则将包含0
这只是以下的简写:
let number = anOptionalInt != nil ? anOptionalInt! : 0
可选链
您可以使用以调用方法或访问可选对象上的属性。使用变量名时,只需在变量名后面加一个?
例如,假设我们有一个变量foo
,其类型为可选的foo
实例
var foo : Foo?
如果我们想在foo
上调用一个不返回的方法
if let nameOfDaughter = nameOfDaughter {
print("My daughters name is: \(nameOfDaughter)")
}
guard let nameOfDaughter = nameOfDaughter else { return }
print("My daughters name is: \(nameOfDaughter)")
enum Optional<Wrapped> : ExpressibleByNilLiteral {
case none
case some(Wrapped)
.
.
.
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DestinationVC{
if let item = sender as? DataItem{
// This line pops up the error
destination.nameLabel.text = item.name
}
}
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let destination = segue.destination as? DestinationVC{
if let item = sender as? DataItem{
// Created this method in the destination Controller to update its outlets after it's being initialized and loaded
destination.updateView(itemData: item)
}
}
}
// This variable to hold the data received to update the Label text after the VIEW DID LOAD
var name = ""
// Outlets
@IBOutlet weak var nameLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
nameLabel.text = name
}
func updateView(itemDate: ObjectModel) {
name = itemDate.name
}
let user = someVariable!
if user = someVariable {
// do your stuff
}
let myRectangle = someShape as! Rectangle
if let myRectangle = someShape as? Rectangle {
// yay, I have a rectangle
}
class User {
var name: String!
init() {
name = "(unnamed)"
}
func nicerName() {
return "Mr/Ms " + name
}
}
class SignInViewController: UIViewController {
@IBOutlet var emailTextField: UITextField!
}
@interface MyUser: NSObject
@property NSString *name;
@end
c1.address.city = c3.address.city
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var c1 = NormalContact()
let c3 = BadContact()
c1.address.city = c3.address.city // compiler hides the truth from you and then you sudden get a crash
}
}
struct NormalContact {
var address : Address = Address(city: "defaultCity")
}
struct BadContact {
var address : Address!
}
struct Address {
var city : String
}
c1.address.city = c2.address!.city // ERROR: Fatal error: Unexpectedly found nil while unwrapping an Optional value
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var c1 = NormalContact()
let c2 = GoodContact()
c1.address.city = c2.address!.city
c1.address.city = c2.address?.city // not compile-able. No deceiving by the compiler
c1.address.city = c2.address.city // not compile-able. No deceiving by the compiler
if let city = c2.address?.city { // safest approach. But that's not what I'm talking about here.
c1.address.city = city
}
}
}
struct NormalContact {
var address : Address = Address(city: "defaultCity")
}
struct GoodContact {
var address : Address?
}
struct Address {
var city : String
}
let nib = UINib(nibName: "CustomnibName", bundle: nil)
self.collectionView.register(nib, forCellWithReuseIdentifier: "cell")