前提:Swift中有规定:对象中的任何属性在创建时,都必须要有明确的初始化值
1.定义可选类型
方式一:常规方式(不常用)
var name : Optional<String> = nil
方式二:语法糖(常用)
var name:String? = nil
Optional理解:
Optional也是Objective-C没有的数据类型,是苹果引入到Swift语言中的全新类型,它的特点就和它的名字一样:可以有值,也可以没有值,当它没有值时,就是nil。此外,Swift的nil也和Objective-C有些不一样,在Objective-C中,只有对象才能为nil,而在Swift里,当基础类型(整形、浮点、布尔等)没有值时,也是nil,而不是一个初始值,没有初始值的值,是不能使用的,这就产生了Optional类型。定义一个Optional的值很容易,只需要在类型后面加上问号(?)就行了:
let nameStr: String?
Optional值和非Optional值的区别就在于:Optional值未经初始化时也为nil,非Optional未初始化时什么都没有,如果直接使用会报错:
//未被初始化,但是是一个Optional类型,为nil
var nameStr: String?
str //输出nil
//未被初始化,也不是Optional类型
var nameStr2: String
str2 //使用时出错
Optional拆包:
Optional类型的值不能被直接使用,当需要用时要显式拆包,以表明我知道这个Optional是一定有值的:拆包的方式是直接在变量后加!
var nameStr: String? = "Hello World!"
nameStr //{Some "Hello World!"}
nameStr! //Hello World!
拆包的原因是因为Optional类型其实是一个枚举:
enum Optional<T> : Reflectable, NilLiteralConvertible {
case None
case Some(T)
init()
init(_ some: T)
/// Haskell's fmap, which was mis-named
func map<U>(f: (T) -> U) -> U?
func getMirror() -> MirrorType
static func convertFromNilLiteral() -> T?
}
拆包的作用就是将值取出来。
隐式拆包:
除了显式拆包,Optional还提供了隐式拆包,通过在声明时的数据类型后面加一个感叹号(!)来实现:
var nameStr: String! = "Hello World!"
nameStr //Hello World!
可以看到没有使用(?)进行显式的折包也得到了Some中的值,这个语法相当于告诉编译器:在我们使用Optional值前,这个Optional值就会被初始化,并且总是会有值,所以当我们使用时,编译器就帮我做了一次拆包。如果你确信你的变量能保证被正确初始化,那就可以这么做,否则还是不要尝试为好。
Optional Binding
var count: Int?
count = 100
if count != nil {
"count is " + String(count!) //count is 100
} else {
"nil"
}
上面代码,如果判断为真,下面将进行拆包,为了避免在条件判断语句后执行一次或更多次的拆包,Swift引进了Optional Binding,我们就可以这样做
var count: Int?
count = 100
if let validCount = count {
"count is " + String(validCount) //count is 100
} else {
"nil"
}
通过在条件判断语句中(如if、while等)把Optional值直接给一个临时常量,Swift会自动检测Optional是否包含值,如果包含值,会隐式的拆包并给那个临时常量,在接下来的上下文中就能直接使用这个临时常量了
注意:强制解包是危险操作,容易导致程序崩溃
建议在强制解包前,先对可选类型进行判断,判断是否为nil
可选绑定
写法一:(不常用)因为每次解包要创建一个新的变量
if let tempName = name{
print(tempName)
}
解释:1.判断name是否有值,如果没有不执行{}内容,如果有值,系统会自动将name解包,并且直接复制给tempName
写法二:(常用),就近原则
if let name = name{
print(name)
}