Download - Optional in swift
? 和 ! 略懂略懂 (︖?!
Optional in Swift Grady Zhuogithub.com/gradyzhuofacebook.com/gradyzhuo
什麼是Optional - 1❖ Swift also introduces optional types, which handle the
absence of a value. Optionals say either “there is a value, and it equals x” or “there isn’t a value at all”. Optionals are similar to using nil with pointers in Objective-C, but they work for any type, not just classes. Optionals are safer and more expressive than nil pointers in Objective-C and are at the heart of many of Swift’s most powerful features.
什麼是Optional - 2❖ Optional是Swift中,做為處理可能存在nil值變數的機制。︒
❖ Optional 是⼀一個enum,存在兩種可能:
❖ Some : 有值存在
❖ None : 無值存在———————————————————————— enum Optional<T> : Reflectable, NilLiteralConvertible { case None case Some(T) }
開始囉
會爆炸的包裹
這個世界裡的包裹,拆開後,如果沒有東西,世界就會毀滅…
別讓上帝不開⼼心
❖ 我們先假設這個世界裡的包裹,拆開後,如果沒有東西,拆上帝就會爆⾛走,然後世界就毀滅了(咦?
❖ 可以要求別⼈人在送包裹的時候,要把東西放在箱⼦子給你。︒
❖ 你隨時可以拆包裹,只是要⼩小⼼心,世界,可能會毀滅…
放進禮物盒❖ 所謂的“放進箱⼦子”這個動作就是由「?」來達成。︒
❖ 我們可以想像成,當你宣告使⽤用了「?」,就像是你準備了⼀一個箱⼦子準備放物品,箱⼦子上⾯面會貼標籤說明這是什麼東西。︒
❖ 當你賦值時,就像是把⼀一個東西放入了「箱⼦子」中,雖然包裹的標籤有說這是什麼東西,但你拿到的還是「盒⼦子」。︒
Int?
String?CGRect?
「?」 做了什麼事呢︖?❖ 「?」 是什麼︖? 「?」是 Optional<T> 的「語法糖衣1」
❖ e.g. 有值的狀況
var i : Int? = 10
var i : Optional<Int> = Optional<Int>.Some(10)
❖ e.g. 沒有值的狀況
var j : Int? = nil
var j : Optional<Int> = Optional<Int>.None
開箱
❖ 開箱這檔事,就是「!」這把「⼑刀」負責。︒
❖ 「!」在術語中又叫 Unwrap
❖ 為什麼「!」最讓⼈人困惑︖?
❖ 因為「!」要分兩種情況說明:
❖ 1. 作為運算⼦子
❖ 2.宣告
!
先說說運算⼦子的狀況
❖ 你可以針對任何Optional的值進⾏行Unwrap
❖ 就像東西重新從箱⼦子又拿出來的意思
❖ e.g. 考慮有值的Optional
❖ var i : Int? = 3
❖ i => Optional(3)
❖ var unwrappedValue = i! => 3 //重新把3拿出來
先說說運算⼦子的狀況
❖ e.g. 如果是沒有值的Optional
❖ var j:Int? = nil
❖ j => Optional(nil)
❖ j! => nil //就會拿到nil了~
先說說運算⼦子的狀況
❖ e.g. 如果是沒有值的Optional
❖ var j:Int? = nil
❖ j => Optional(nil)
❖ j! => nil //就會拿到nil了
因為當運算⼦子的「!」 是unwrapping, 所以⼀一定要取到東西
會Crash!!!!
宣告時⽤用的「!」❖ 宣告的狀況下,「!」跟「?」的⾏行為類似, 都可以塞進nil。︒
❖ 但使⽤用時,如果是nil,就會Crash...(Why?
❖ e.g. 有值的狀況
var i : Int! = 3
var k = i + 1 => 3 //不是Optional
❖ e.g. 沒有值的狀況
var j : Int!
var l = j + 1 //Crash
宣告時的「!」,做了什麼︖? - 1❖ 宣告時使⽤用「!」就像在箱⼦子旁邊貼著⼀一把「⼑刀」,這把⼑刀就像被動技能⼀一樣,只要操作variable,就會⾃自動啟動Unwrapping。︒
❖ e.g. 剛剛有值的例⼦子
❖ var i : Int! = 3
❖ var k = i + 1 => 3
//所以上⾯面的寫法,會等於下⾯面的寫法。︒
❖ var i : Int? = 3
❖ var k = i! + 1 => 3 //因為i有值,所以unwrap有值,⼀一切正常。︒
錢鬼,我還你原形!(誤
宣告時的「!」,做了什麼︖? - 2
//同理,回來討論nil的狀況
var j : Int!
var l = j + 1 //Crash
//等於下⾯面寫法
var j : Int?
var l = j! + 1 //因為j沒有值,是個nil, 所以會Crash,⽽而且crash在j!的地⽅方
宣告時⽤用「!」跟「︖?」的不同
❖ 「?」:就是你想⽤用這個參數時,你必須先找⼀一把⼑刀⼦子才能開箱,所以Xcode會強迫你去處理Optional的變數。︒
❖ 「!」:因為Unwrap會⾃自動進⾏行,所以⽤用「!」的變數跟沒有宣告Optional⼀一樣,可以直接使⽤用變數的值,所以可以不⽤用進⾏行任何處理,但就會出現隱憂,程式隨時都會Crash.
使⽤用時該怎麼選呢︖?
除非除非除非(很重要,所以說三次)你很確定,這個變數裡⼀一定有值,只是現在宣告沒辦法先給,那你就可以⽤用「!」
e.g.
1. 與UI連動的@IBOutlet,因為你⼀一定會連到某⼀一個UI上,只是因為宣告不可能給實體,所以你就可以先設定成「!」。︒
(通常你不拉這個outlet,程式也運⾏行不正確)
2. 你了解⾃自已的架構,會正確無誤,那也可以⽤用「!」宣告。︒
總⽽而⾔言之,⾔言⽽而總之
不要為了「懶」⽽而使⽤用「!」,⼑刀劍無情!
⼈人在江湖漂,那有不挨⼑刀(︖?
兩個⼩小技巧
❖ 在拆包裹時,你可以選擇引發神蹟,如果本來沒東西,至少會冒出個⼩小確幸可以拿到。︒(別讓⾃自已不開⼼心
❖ 如果包裹有好幾層,你也可以選擇躲在箱⼦子裡拆包裹,然後可能就在箱⼦子裡⾃自爆了。︒(︖?
??❖ Swift導入了 「??」⼆二元運算⼦子,他的規則如下:
❖ (Value) = Optional(T) ?? (Default Value)
❖ 如果「??」左邊為nil, 會回傳「??」右邊的的值(通常是Default值)
❖ e.g.
❖ var i : Int? = 3
❖ var j = i ?? 0 // j == 3
❖ ——————————-
❖ var i:Int?
❖ var j = i ?? 0 // j == 0
Optional Chaining❖ Optional chaining is a process for querying and calling properties,
methods, and subscripts on an optional that might currently be nil.
❖ 可以在好幾層的Optional中使⽤用「?.」的語法取值操作,若過程中有任何操作出現nil, 會直接回傳nil, 且接下來的事情都不會進⾏行,也不會crash。︒
❖ var array:[Int]? = []
❖ array?.append(0)
❖ //
❖ var array2:[Int]?
❖ array2?.append(1) //不會crash, 且什麼事都不會發⽣生
補充
What is enum枚舉是⼀一個被命名的整型常數的集合,枚舉在⽇日常⽣生活中很常⾒見,例如表⽰示星期的SUNDAY、MONDAY…SATURDAY就是⼀一個枚舉。 枚舉的說明與結構相似,其形式為:
enum 集合命名[:元素的類型]{ case 元素1[=值] case 元素2[=值] ... case 元素n[=值] }
enum Week : Int{ case SUNDAY = 0 case MONDAY = 1 case TUESDAY = 2 case WEDNESDAY = 3 case THURSDAY = 4 case FRIDAY = 5 case SATURDAY = 6 }
enum in Swift
//: Swift中的enum有⼀一個特例的⽤用法,那就是可以塞東⻄西
enum MyEnum { case Value(str:String) }
//: 這樣我們可以做出許多都是MyEnum的enum變數,但內容不⼀一樣
var enum1 = MyEnum.Value(str: "Hello") var enum2 = MyEnum.Value(str: "World")
enum in Swift//: 也可以取出他們的值 func getValue(enumValue:MyEnum)->String{ switch enumValue { case let .Value(str): return str } }
let enum1Value = getValue(enum1) //enum1Value == “Hello” let enum2Value = getValue(enum2) //enum2Value == “World”
名詞解釋
❖ 語法糖衣:使⽤用更簡潔的語法,簡化原本較為繁瑣但完整的語法。︒