为什么没有分配隐式解包的可选项?

时间:2017-04-08 00:00:00

标签: swift optional forced-unwrapping

在下面的代码中,为什么5未分配给“somevar”?

images.push({ name: "bla", image: "base64..." })

背景

class ViewController: UIViewController { var somevar : Int? override func viewDidLoad() { super.viewDidLoad() somevar! = Int(5) // why 5 is not assigned to somevar here } } 被声明为可选变量,这意味着如果此变量为nil,则将忽略使用此变量的命令。

示例:

somevar

为了强行执行命令,我们使用“Implicitly unwrapped optional”,这样我们就可以确保执行命令,在这种情况下执行以下行

class ViewController: UIViewController {

    var somevar : Int?

    override func viewDidLoad() {
        super.viewDidLoad()
        somevar? = 5 // this command will be ignored bcz somevar is nil
    }
}
  

致命错误:在解包可选值时意外发现nil

执行此行时,为什么“5”未分配给“somevar”而是发生致命错误?

somevar! = 5 

2 个答案:

答案 0 :(得分:2)

当我们something!(强调标记)时,我们就是" 强制阅读" (强行展开)一个可选项。

也就是说,上面的代码在为其赋予新值之前会尝试阅读something 由于somethingnil,因此代码会爆炸。

举例说明:

var somevar: Int?

print(somevar!)
// Code explodes! 

print(somevar)
// Output is "nil"

somevar = 5

print(somevar!)
// Output is "5"

print(somevar)
// Output is "Optional(5)"

正如@LeoDabus所述,Apple's awesome Swift book涵盖了这一点 (BTW一本非常好的书!❤️)

答案 1 :(得分:0)

somevar? = 5正在做的事情提供一些颜色。

//: Playground - noun: a place where people can play

import Foundation

// In swift you have to unwrap an optional before you can do anything with it
var x: Int? = 1
var y: Int? = 2

// So you can't do this
//var z = x + y

// You have to do this
if let x = x,
    let y = y {
    // Here x and y are no longer of the type Int? they are of the type Int
    var z = x + y
}

// You don't have to name them the same
if let someX = x,
    let someY = y {
    // Here x and y are no longer of the type Int? they are of the type Int
    var z = someX + someY
}

// This can be a pain sometimes if you want to "do nothing" in the nil case, or want to unwrap something multiple "levels"
// of optionals deep. For example:

struct Pet {
    let name: String
}

struct Person {
    let pet: Pet?
}

var person: Person? = Person(pet: Pet(name: "Rex"))

// To get the person's pet's name we have to unwrap a few things
if let person = person,
    let pet = person.pet {
    print("The pet's name is \(pet.name)")
}

// We can do this a little easier by using "Optional Chaining"
if let name = person?.pet?.name {
    print("The pet's name is \(name)")
}

// So here's where your problem comes in
var number: Int? = nil

// This is "optional chaining" the assignment of 5 to number. But, because number is current nil the assignment won't happen.
number? = 5

// However
number = 5

// Now the number is 5

number? = 10

// Now the number is 10, because the optional chaining succeded because number was not nil. All this being said, I've never
// seen someone use x? = 5 in production code, and I can't think of a reason to do that. Just do x = 5 like the other
// answers have said.

TL; DR,somevar? = 5正在使用可选链接仅将somevar设置为5,如果它不是nil