在Swift中声明属性有三种方法:
var optStr: String?
var normStr: String = "normStr"
var exactStr: String!
第一个是optional
类型的属性,在我们的例子中可以包含nil或String的类型。第二个是始终包含String的属性。它应该在init或声明中初始化。
但是第三种方式呢?
var exactStr: String!
我在操场上做了一些实验,结果表明,type?
的函数可以将type
,type?
和type!
变量作为参数:
var optStr: String?
var normStr: String
var forcedStr: String!
func printStr(str: String?) {
println("str: \(str)")
}
printStr(optStr) //prints: "str: nil"
//printStr(normStr) //doesn't compile as not initialized
printStr(forcedStr) //prints: "str: nil"
optStr = "optStr"; normStr = "normStr"; forcedStr = "forcedStr"
printStr(optStr) //prints "str: optStr"
printStr(normStr) //prints "str: normStr"
printStr(forcedStr) //prints "str: forcedStr"
那么为什么以及何时应该使用type!
?
更新:这不是What does an exclamation mark mean in the Swift language?的重复。我没有询问展开变量:我问declaring
一个带感叹号的属性(Type!
)。
答案 0 :(得分:65)
它是"隐式解包的可选字符串"类型的变量。从本质上讲,implicitStr
的每次访问都被视为写入implicitStr!
(因此展开了值)。
当然,如果值为零,这将导致崩溃。您仍然可以通过if implicitStr != nil
测试隐式可选项,或者在可选链接中将其用作var foo = implicitStr?.uppercaseString
。所以你仍然可以像普通的可选项一样安全地使用它;它只是偏向于价值不是零的情况。
隐式解包的选项在初始化时可能不存在的情况下非常有用,但是提前设置并且不太可能再次变为零。 (例如,您在-awakeFromNib中设置的变量可能合理地是一个隐式解包的可选项。)
此外,由于Objective-C方法可以返回nil和object类型,因此无法将其返回值建模为非可选。但是,为避免在处理Cocoa API时需要自由使用强制解包,Cocoa API的参数和返回类型通常表示为隐式解包的选项。