Swift纠结:optional 的!和?

optional

本文为对 swift自我学习的理解,如有错误,还望纠正。

Optional的定义:

它的特点就和它的名字一样:可选值类型。可以有值,也可以没有值,当它没有值时,就是nil。

一、与 object-c区别:

  • 在Objective-C中,只有对象才能为nil
    而在Swift里,当基础类型(整形、浮点、布尔等)没有值时,也是nil,而不是一个初始值,没有初始值的值,是不能使用的。

二、optional的使用

var str: String?

理解optional:

  • Optional值未经初始化虽然为nil,但普通变量没有。即:optional 为 nil 状态(无值状态) 与确定值(值为多少取决于你付的值)状态。而其他类型相当于是 空值(像 C 的野指针,会报错)和确定值。
var str: String?   //未被初始化,但是是一个Optional类型,为nil
str //输出nil

var str2: String //未被初始化,也不是Optional类型
str2    //使用时出错

optional结构:

var str: String?  = "Hello World!" //未被初始化,但是是一个Optional类型,为nil
println(str) //输出 : {Some "Hello World!"}

可看出 value 其实存储于一个枚举中,要访问其值要拆包才行.
结构如下:

enum Optional<T> : Reflectable, NilLiteralConvertible {
    case None   //swift 会省略 break;要进入下一个 case 要在末尾加 fallthrough
                       //此处有个省略的break;(我的理解)
    case Some(T)
    init()
    init(_ some: T)

   /** 此处我还未理解=_= **/
    func map<U>(f: (T) -> U) -> U?
    func getMirror() -> MirrorType
    static func convertFromNilLiteral() -> T?
}
可见,nil=>Optional.None,即没有值。当有值时就是被Some<T>包装的真正的值,所以我们拆包的动作其实就是将Some里面的值取出来。

三、Optional的拆包。

1.显式拆包
在变量后添加 ! 即可快捷拆包(还有另一种正常方式,比较麻烦,一般不会使用,所以就不列出了)

var str: String? = "Hello World!"
println(str)      //输出: {Some "Hello World!"}
println(str!)    //输出: Hello World!

2.隐式拆包

var str: String! = "Hello World!" //注意 String 后的!号
println(str) //Hello World!

但不建议这种做法,从上可得,若 str 无值时会直接报错。可见其实 swift 是不希望我们这样使用的,所以特地有一个可选择类型加强评断的逻辑性。
使用前提:确定变量定会有值时使用。

3.optional binding (判断自动解包)
当在判断语句中赋值 optional 类型给,临时常量(或变量),会自动解包(不用加!号)

var count: Int?
count = 100
if let validCount = count { // optional binding ,不用加!解包,自动解包
    "count is " + String(validCount)    //count is 100而不是{some 100}
} else {
    "nil"
}

4.optional chaining(可选判断链)

class man {
    var pet: Pet?
}

class Pet {
    var name: String
    var Toy: Toy?
    
    init (name: String) {
        self.name = name
    }
}

如上,某人的可能有宠物狗,并且宠物狗可能会有自己的玩具.根据上面为了安全要如下binding:

let Tom = man()
Tom.pet = Pet(name: "dog")
Tom.pet?.Toy = Toy(name: "toy")
if let pet = Tom.pet { //判断是否有宠物
    if let toy = pet.Toy { //判断有无玩具
        toy.name //经过多重判断才能确保有值
    }
}

以上,两层数就要解包两次,N 层呢? 所以出了 optional chaining 只要判断最里层有无,会自动判断中间层是否为 nil ,只要其中一层为 nil ,则整体为 nil.即:

if let toy = Tom.pet?.Toy { //最里层的 Toy,中间层 pet? 
    toy.name
}

代码简单多了~

老规矩,学习原址:http://blog.csdn.net/zhangao0086/article/details/38640209

posted @ 2015-05-30 00:17  Orange-W  阅读(293)  评论(0编辑  收藏  举报