在Swift中强制展开

时间:2014-09-10 12:54:02

标签: swift

我有以下实现,我需要访问streetName,如下所示:

if let street = john.residence?.address?.streetName {

    street // Darling Lane // This prints string correctly 
}

let street = john.residence?.address?.streetName! // Some "Darling Lane" The bang sign //  at the end does not forcefully unwraps the optional

有什么理由?

更新:

好的,我现在很困惑!这是完整的代码:

class Person {
    var residence :Residence? = Residence()
}

class Residence {
    var address :Address? = Address()
}

class Address {
    var streetName :String? = "Darling Lane"
    var zipCode :String?
    var city :String?
}


let street = john.residence?.address?.streetName! 

在上面的代码中我说如果居住地不是空的话他们继续前进。当你到达streetName然后给我一个我不在乎的值如果streetName是nil只是抛出错误但是正确评估它。

最后的街道参数包含Some" Darling Lane"而不是"达林巷"。这是为什么?

3 个答案:

答案 0 :(得分:2)

您的可选链末尾的!只会打开可选的streetName而不是您预期的整个可选链。如果已将streetName声明为String类型而非String?String!,则您会收到有关尝试解包非可选值的错误。

如果你这样做了:

let street = (john.residence?.address?.streetName)!
它会起作用。当然,如果residenceaddressstreetName中的任何一个nil,您就会崩溃尝试解包nil。这就是为什么你提出的第一种方法是首选。

回答更新

只有可选变量可以是nil。这就是为什么可选链的结果必须具有可选类型。

street的类型是在编译时建立的。编译器看到您有一系列可选项,并使street属于String?类型。你在链的末尾打开街道的价值并不重要。由于residenceaddress可能是nil,因此选项链可能返回nil,因此编译器必须使street的类型成为可选如果是结果,它可以保留nil

当你这样写:

let street = john.residence?.address?.streetName!

这基本上就是你的代码所做的事情:

var street: String?
if john.residence == nil {
     street = nil
} else if john.residence!.address == nil {
    street = nil
} else {
    // here we have fully unwrapped the street name
    // but it is still assigned to street which
    // is an optional variable
    street = john.residence!.address!.street!
}

唯一的区别在于它是一次性完成的,因此您可以使用let代替var

答案 1 :(得分:1)

发生这种情况的原因是residenceaddress都是选项,因此可选链的评估结果为nil。因此,整个表达式被评估为可选。

要获得非可选值,您必须强行打开所有属性:

let street: String = john.residence!.address!.streetName!

但当然如果该链中的任何选项都是nil,您将获得运行时异常

答案 2 :(得分:1)

代码中的选项是有原因的,如果您已经检查了选项的值,则只需要显式解包变量。如果值不存在,您的应用将崩溃

立即解开街道名称的正确方法是:

john.residence!.address!.streetName

仅展开residenceaddress,如果其中任何一个未设置,则会引发异常。如果streetName也是可选的,则您需要在结尾添加另一个!

确保您确定自己的数据结构。最好先选择非选项,如果一个人没有residenceaddress,你就需要选项。但如果您使用选项,请确保它们都已经过检查!

Optionals可以使您的代码更安全,更易于阅读,但您必须正确使用它们。