在變數宣告上寫作
var s:String = "s" var s0:String! var s1:String! = "s1" var ss0:String? var ss1:String? = "ss1"
其中s不可為空值,s0, s1, ss0, ss1 可為空值,s0, s1 預設不為空值,ss0, ss1 預設為空值。
在變數使用上,假設我們現在要做的事情是取得字串長度,預設為空值的變數必須經過一個轉換才能使用,基本的用法如下:
1. 用 lf let 解開變數封裝
var stringLength1:Int = 0 if let ss0 = ss0 { //如果ss0有值會進入這裡,且ss0的型別被改為String stringLength1 = ss0.utf16Count } else { //如果是空值會進入這裡 }
2. 用問號,當 ss0 是 nil 時 return nil ,所以等號左邊必須也用可為空值的變數去接
var stringLength2:Int! stringLength2 = ss0?.utf16Count
3. 用驚嘆號強制解開變數封裝,這種寫法當 ss0 是 nil 時程式就 crash
var stringLength3:Int stringLength3 = ss0!.utf16Count
方法 1 清楚地描述了 ss0 是空值或不是空值分別該怎麼做。
方法 2 是說當 ss0 是空值時,stringLength2 就設為空值。
方法 3 則是當 ss0 是空值時,程式就要 crash。
方法 1 或方法 2 都有處理當 ss0 為 nil 時該怎麼做,而方法 3 沒有,所以方法 3 是危險的。
也許我們可以當 ss0 為空值時給 ss0 一個預設值,讓程式繼續執行下去,做法如下:
if ss0 == nil { ss0 = "nil" }
或
ss0 = ss0 == nil ? "nil" : ss0
我們把設定預設值的動作寫成函數,以便日後使用。
public func unwarp(string:String?) -> String{ return string == nil ? "nil" : string! } unwarp(ss0) // return "nil" unwarp(ss1) // return "ss1"
我們也可以也把它寫成泛型,並且加入預設值的設定。
public func unwarp<T>(value:T?, defaultValue:T) -> T{ return value == nil ? defaultValue : value! } unwarp(ss0, "XDDD") // return "XDDD" unwarp(ss1, "XDDD") // return "ss1"
於是我們可以對所有型別都做出 unwarp function。
*** 2014/10/9 更新 ***
上述的泛型 unwarp 函數在輸入的兩個變數型別不同時會以 value 為主
以下的 code 修正這個問題,改為以 defaultValue 的型別為主
public func unwarp(value:AnyObject?, defaultValue:T)->T{ if let value: AnyObject = value { return value is T ? value as T : defaultValue }else{ return defaultValue } } unwarp("1.0",0.0) // return 0.0 unwarp(1.0,0.0) // return 1.0 unwarp(nil,0.0) // return 0.0 var a1:Int = unwarp(3.5,1.5) // a1 = 3 var a2:Int = unwarp("3.5",1.5) // a2 = 1
*** 2015/2/12 更新 ***
發現內建處理解開封印時加入預設值的運算子 ??
var ss:String? ss ?? "QQ" // return QQ
1 則留言:
Wrap
張貼留言