swift 可选值总结
先看几个例子:
var optionalStr : String!
//声明可选值,默认为nil
optionalStr = nil
if optionalStr == nil {
// 通过条件判断
}
当初看到这段代码时,非常奇怪,按照之前浅显的理解,被标记为!的应该必然有值啊,这段代码应该报错才对啊?后面仔细查看文档,才理解了这段代码
Optional的定义
Optional也是Objective-C没有的数据类型,是苹果引入到Swift语言中的全新类型,它的特点就和它的名字一样:可以有值,也可以没有值,当它没有值时,就是nil。此外,Swift的nil也和Objective-C有些不一样,在Objective-C中,只有对象才能为nil,而在Swift里,当基础类型(整形、浮点、布尔等)没有值时,也是nil,而不是一个初始值,没有初始值的值,是不能使用的,这就产生了Optional类型。
简单来说:
var nonoptionalStrStr: String
这是非可选类型
var optionalStrStr: String?
var optionalStrStr: String!
这都是可选类型
非可选类型的特点
var nonoptionalStrStr: String
NSLog(nonoperationStr)
//error: variable 'nonoperationStr' used before being initialized
//表示非可选类型必须初始化才能使用
nonoperationStr = nil
//error: nil cannot be assigned to type 'String'
//说明 nil 也是一种数据类型,不能够赋值给string类型的对象,
//从这个角度说,使用非可选类型更不容易出错
可选类型
显式拆包
Optional类型的值不能被直接使用,当需要用时要显式拆包,以表明我知道这个Optional是一定有值的:
var str: String? = "Hello World!"
str! //Hello World!
对比拆包前后,对str的输出
var str: String? = "Hello World!"
str //{Some "Hello World!"}
str! //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没有值时,返回的nil其实就是Optional.None,即没有值。除了None以外,还有一个Some,当有值时就是被Some
隐式拆包
除了显式拆包,Optional还提供了隐式拆包,通过在声明时的数据类型后面加一个感叹号(!)来实现:
var str: String! = "Hello World!"
str //Hello World!
可以看到没有使用(?)进行显式的折包也得到了Some中的值,这个语法相当于告诉编译器:在我们使用Optional值前,这个Optional值就会被初始化,并且总是会有值,所以当我们使用时,编译器就帮我做了一次拆包。如果你确信你的变量能保证被正确初始化,那就可以这么做,否则还是不要尝试为好。
所以,使用!真的是一件非常危险的事,它并不表示这个值使用一定是安全的,它只是表明开发人员认为这个值有值,编译器并不会检查,不小心很容易出错。