Swift 可选链接和绑定

Swift 可选链接和绑定,swift,Swift,在可选绑定中,当我分配变量ammo(和ammo2)时,我非常确定我应该使用取消对可选项的装箱,但在我第一次尝试时,我错误地放入了?,有点困惑为什么它仍然有效,有人能解释一下那里发生了什么吗 let soldierA = Soldier(name: "Brian") soldierA.weapon = Weapon() soldierA.weapon!.grenadeLauncher = GrenadeLauncher() let soldierB = Soldier(name: "Gavin"

在可选绑定中,当我分配变量ammo(和ammo2)时,我非常确定我应该使用
取消对可选项的装箱,但在我第一次尝试时,我错误地放入了
,有点困惑为什么它仍然有效,有人能解释一下那里发生了什么吗

let soldierA = Soldier(name: "Brian")
soldierA.weapon = Weapon()
soldierA.weapon!.grenadeLauncher = GrenadeLauncher()

let soldierB = Soldier(name: "Gavin")
soldierB.weapon = Weapon()

let soldierC = Soldier(name: "Berty")
soldierC.weapon = Weapon()
soldierC.weapon!.grenadeLauncher = GrenadeLauncher()
soldierC.weapon!.grenadeLauncher!.ammo = 234

let missionTeam = [soldierA, soldierB, soldierC]
for eachSoldier in missionTeam {
    if let launcherAvailable = eachSoldier.weapon?.grenadeLauncher? {
        var ammo =  eachSoldier.weapon!.grenadeLauncher!.ammo // PRETTY SURE THIS IS RIGHT
        var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo // SHOULD THIS WORK, IT DOES?
        println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo)")
    } else {
        println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
    }
}

编辑 谢谢你,我对它的工作原理感到困惑,但现在我明白了。这里是修改后的eachSoldier部分,使用可选绑定和可选链接

for eachSoldier in missionTeam {
    if let weapon = eachSoldier.weapon? {
        if let launcher = eachSoldier.weapon?.grenadeLauncher? {
            println("SOLDIER: \(eachSoldier.name) Weapon has launcher with \(launcher.ammo) ammo")
        } else {
            println("SOLDIER: \(eachSoldier.name) Weapon does not have launcher ")
        }
    } else {
        println("SOLDIER: \(eachSoldier.name) does not have weapon ")
    }
}
这在当前模式中是正确的


隐式打开
武器
及其
手榴弹发射器
;它不关心它们之前是否被初始化过,因此,如果您的代码试图在它们中的任何一个仍然是
nil
值时展开,则可能导致直接崩溃


尝试访问
武器
及其
手榴弹发射器
;如果对象不存在,它们将被单独保留,因此除了
ammo2
将仅为
nil
之外,不会发生任何事情,并且应用程序可以继续

因此,您的流程可能类似于:

for eachSoldier in missionTeam {
    var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
    if ammo2 != nil {
        println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo2)")
    } else {
        println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
    }
}
这在当前模式中是正确的


隐式打开
武器
及其
手榴弹发射器
;它不关心它们之前是否被初始化过,因此,如果您的代码试图在它们中的任何一个仍然是
nil
值时展开,则可能导致直接崩溃


尝试访问
武器
及其
手榴弹发射器
;如果对象不存在,它们将被单独保留,因此除了
ammo2
将仅为
nil
之外,不会发生任何事情,并且应用程序可以继续

因此,您的流程可能类似于:

for eachSoldier in missionTeam {
    var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
    if ammo2 != nil {
        println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo2)")
    } else {
        println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
    }
}
这在当前模式中是正确的


隐式打开
武器
及其
手榴弹发射器
;它不关心它们之前是否被初始化过,因此,如果您的代码试图在它们中的任何一个仍然是
nil
值时展开,则可能导致直接崩溃


尝试访问
武器
及其
手榴弹发射器
;如果对象不存在,它们将被单独保留,因此除了
ammo2
将仅为
nil
之外,不会发生任何事情,并且应用程序可以继续

因此,您的流程可能类似于:

for eachSoldier in missionTeam {
    var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
    if ammo2 != nil {
        println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo2)")
    } else {
        println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
    }
}
这在当前模式中是正确的


隐式打开
武器
及其
手榴弹发射器
;它不关心它们之前是否被初始化过,因此,如果您的代码试图在它们中的任何一个仍然是
nil
值时展开,则可能导致直接崩溃


尝试访问
武器
及其
手榴弹发射器
;如果对象不存在,它们将被单独保留,因此除了
ammo2
将仅为
nil
之外,不会发生任何事情,并且应用程序可以继续

因此,您的流程可能类似于:

for eachSoldier in missionTeam {
    var ammo2 = eachSoldier.weapon?.grenadeLauncher?.ammo
    if ammo2 != nil {
        println("SOLDIER: \(eachSoldier.name), Weapon has launcher AMMO: \(ammo2)")
    } else {
        println("SOLDIER: \(eachSoldier.name), Weapon does not have launcher ")
    }
}
除了上面所说的,我想说的是您的案例调用了,如果您使用
而不是
表示您正在检查变量(或常量)是否为nil。换句话说,它是有价值的

可选链接的好处在于,您可以将其应用于多个级别。 例如:

假设您有以下两个类:

class Student{
    var subjects: [Subject]?
}
class Subject{
    var name: String?
}
您创建了一个变量:

var william = Student()
您可以随时打印第一个主题的名称,如下所示:

print(william.subjects?[0].name)
请注意,该print语句的结果是nil,而如果按如下方式展开:

print(william.subjects![0].name)
您将得到一个运行时错误

除了前面所述之外,我想说您的案例调用了,如果您使用
而不是
表示您正在检查变量(或常量)是否为nil。换句话说,它是有价值的

可选链接的好处在于,您可以将其应用于多个级别。 例如:

假设您有以下两个类:

class Student{
    var subjects: [Subject]?
}
class Subject{
    var name: String?
}
您创建了一个变量:

var william = Student()
您可以随时打印第一个主题的名称,如下所示:

print(william.subjects?[0].name)
请注意,该print语句的结果是nil,而如果按如下方式展开:

print(william.subjects![0].name)
您将得到一个运行时错误

除了前面所述之外,我想说您的案例调用了,如果您使用
而不是
表示您正在检查变量(或常量)是否为nil。换句话说,它是有价值的

可选链接的好处在于,您可以将其应用于多个级别。 例如:

假设您有以下两个类:

class Student{
    var subjects: [Subject]?
}
class Subject{
    var name: String?
}
您创建了一个变量:

var william = Student()
您可以随时打印第一个主题的名称,如下所示:

print(william.subjects?[0].name)
请注意,该print语句的结果是nil,而如果按如下方式展开:

print(william.subjects![0].name)
您将得到一个运行时错误

除了前面所述之外,我想说您的案例调用了,如果您使用
而不是
表示您正在检查变量(或常量)是否为nil。换句话说,它是有价值的

可选链接的好处在于,您可以将其应用于多个级别。 例如:

假设您有以下两个类:

class Student{
    var subjects: [Subject]?
}
class Subject{
    var name: String?
}
您创建了一个变量:

var william = Student()
您可以随时打印第一个主题的名称,如下所示:

print(william.subjects?[0].name)
请注意,该print语句的结果是nil,而如果按如下方式展开:

print(william.subjects![0].name)
您将得到一个运行时错误