使用可选链接,如果我有一个Swift变量
var s: String?
可能包含nil,或者包含在Optional中的String。所以,我尝试了这个来获得它的长度:
let count = s?.characters?.count ?? 0
然而,编译器想要这个:
let count = s?.characters.count ?? 0
我对可选链接的理解是,一旦开始在虚线表达式中使用?.
,其余属性都是可选的,通常由?.
访问,而不是.
所以,我进一步挖了一下并在操场上试了一下:
var s: String? = "Foo"
print(s?.characters)
// Output: Optional(Swift.String.CharacterView(_core: Swift._StringCore(_baseAddress: 0x00000001145e893f, _countAndFlags: 3, _owner: nil)))
结果表明s?.characters
确实是一个Optional实例,表明s?.characters.count
应该是非法的。
有人可以帮我理解这种情况吗?
答案 0 :(得分:5)
当你说:
我对可选链接的理解是,一旦开始在虚线表达式中使用
?.
,其余属性都是可选的,通常由?.
访问,而不是.
我会说你几乎就在那里。
并非所有属性都是可选的,原始调用是可选的,因此看起来其他属性是可选的。
characters
不是可选属性,也不是count
,但您调用它的值是可选的。如果有值,则characters
和count
属性将返回一个值;否则,返回nil
。正因为如此,s?.characters.count
的结果会返回Int?
。
如果其中一个属性是可选的,那么您需要向其添加?
,但是,在您的情况下,它们不是。所以你没有。
编辑以下评论
来自评论:
我仍然觉得
s?.characters.count
和(s?.characters)?.count
编译都很奇怪,但(s?.characters).count
却没有。为什么第一个和最后一个表达式之间存在差异?
我会在这里尝试回答,其中有更多空间而不是评论栏:
s?.characters.count
如果s
为nil,则整个表达式返回nil
,否则返回Int
。因此返回类型为Int?
。
(s?.characters).count // Won’t compile
打破这种情况:如果s
为nil
,则(s?.characters)
为nil
,因此我们无法在其上调用count
。
为了在count
上调用(s?.characters)
属性,表达式需要可选地解包,即写成:
(s?.characters)?.count
已编辑以进一步添加
我能解释的最好的方法是使用这个游乐场代码:
let s: String? = "hello"
s?.characters.count
(s?.characters)?.count
(s)?.characters.count
((s)?.characters)?.count
// s?.characters.count
func method1(s: String?) -> Int? {
guard let s = s else { return nil }
return s.characters.count
}
// (s?.characters).count
func method2(s: String?) -> Int? {
guard let c = s?.characters else { return nil }
return c.count
}
method1(s)
method2(s)
答案 1 :(得分:2)
在Swift-users邮件列表中,Ingo Maier非常友好地指出了Swift语言规范中的section on optional chaining expressions,其中指出:
如果包含可选链接表达式的后缀表达式嵌套在其他后缀表达式中,则只有最外层表达式返回可选类型。
继续举例:
var c: SomeClass?
var result: Bool? = c?.property.performAction()
这解释了为什么编译器在上面的示例中需要 s?.characters.count ,我认为它回答了原始问题。然而,正如@Martin R在评论中观察到的那样,编译器对这两个表达式的不同处理方式仍然存在一个谜:
s?.characters.count
(s?.characters).count
如果我正确阅读规范,那么子表达式
(s?.characters)
"嵌套在"整体后缀表达
(s?.characters).count
因此应该与非括号版本一样对待。但这是一个单独的问题。
感谢大家的贡献!