Swift語言使用var定義變量春寿,但和別的語言不同笔喉,Swift里不會(huì)自動(dòng)給變量賦初始值,也就是說變量不會(huì)有默認(rèn)值鬼雀,所以要求使用變量之前必須要對其初始化顷窒。如果在使用變量之前不進(jìn)行初始化就會(huì)報(bào)錯(cuò):
var stringValue : String
//error: variable 'stringValue' used before being initialized
//let hashValue = stringValue.hashValue
// ^
let hashValue = stringValue.hashValue
上面了解到的是普通值,接下來Optional值要上場了。經(jīng)喵神提醒鞋吉,Optional其實(shí)是個(gè)enum鸦做,里面有None和Some兩種類型。其實(shí)所謂的nil就是Optional.None, 非nil就是Optional.Some, 然后會(huì)通過Some(T)包裝(wrap)原始值谓着,這也是為什么在使用Optional的時(shí)候要拆包(從enum里取出來原始值)的原因, 也是PlayGround會(huì)把Optional值顯示為類似{Some "hello world"}的原因泼诱,這里是enum Optional的定義:
enum Optional<T> : LogicValue, Reflectable {
case None
case Some(T)
init()
init(_ some: T)
/// Allow use in a Boolean context.
func getLogicValue() -> Bool
/// Haskell's fmap, which was mis-named
func map<U>(f: (T) -> U) -> U?
func getMirror() -> Mirror
}
聲明為Optional只需要在類型后面緊跟一個(gè)?即可。如:
var strValue: String? //?相當(dāng)于下面這種寫法的語法糖
var strValue: Optional<Int>
一旦聲明為Optional的赊锚,如果不顯式的賦值就會(huì)有個(gè)默認(rèn)值nil治筒。判斷一個(gè)Optional的值是否有值,可以用if來判斷:
if strValue {
//do sth with strValue
}
然后怎么使用Optional值呢舷蒲?文檔中也有提到說耸袜,在使用Optional值的時(shí)候需要在具體的操作,比如調(diào)用方法牲平、屬性堤框、下標(biāo)索引等前面需要加上一個(gè)?,經(jīng)喵神指正纵柿,”O(jiān)ptional Chaining的問號(hào)的意思是詢問是否響應(yīng)后面這個(gè)方法蜈抓,和原來的isResponseToSelector有些類似”,如果是nil值昂儒,也就是Optional.None沟使,固然不能響應(yīng)后面的方法,所以就會(huì)跳過荆忍,如果有值格带,就是Optional.Some撤缴,可能就會(huì)拆包(unwrap)刹枉,然后對拆包后的值執(zhí)行后面的操作,比如:
let hashValue = strValue?.hashValue
strValue是Optional的字符串屈呕,如果strValue是nil微宝,則hashValue也為nil,如果strValue不為nil虎眨,hashValue就是strValue字符串的哈希值
到這里我們看到了?的兩種使用場景:
聲明Optional值變量
用在對Optional值操作中蟋软,用來判斷是否能響應(yīng)后面的操作
另外,對于Optional值嗽桩,不能直接進(jìn)行操作岳守,否則會(huì)報(bào)錯(cuò):
//error: 'String?' does not have a member named 'hashValue'
//let hashValue = strValue.hashValue
// ^ ~~~~~~~~~
let hashValue = strValue.hashValue
上面提到Optional值需要拆包(unwrap)后才能得到原來值,然后才能對其操作碌冶,那怎么來拆包呢湿痢?拆包提到了幾種方法,一種是Optional Binding, 比如:
if let str = strValue {
let hashValue = str.hashValue
}
還有一種是在具體的操作前添加!符號(hào)譬重,這又是什么語法?!
例子拒逮,strValue是Optional的String:
let hashValue = strValue!.hashValue
這里的!表示“我確定這里的的strValue一定是非nil的,盡情調(diào)用吧” 臀规,比如這種情況:
if strValue {
let hashValue = strValue!.hashValue
}
{}里的strValue一定是非nil的滩援,所以就能直接加上!,強(qiáng)制拆包(unwrap)并執(zhí)行后面的操作塔嬉。 當(dāng)然如果不加判斷玩徊,strValue不小心為nil的話,就會(huì)出錯(cuò)谨究,crash掉佣赖。
考慮下這一種情況,我們有一個(gè)自定義的MyViewController類记盒,類中有一個(gè)屬性是myLabel憎蛤,myLabel是在viewDidLoad中進(jìn)行初始化。因?yàn)槭窃趘iewDidLoad中初始化纪吮,所以不能直接聲明為普通值:var myLabel : UILabel俩檬,因?yàn)榉荗ptional的變量必須在聲明時(shí)或者構(gòu)造器中進(jìn)行初始化,但我們是想在viewDidLoad中初始化碾盟,所以就只能聲明為Optional:var myLabel: UILabel?, 雖然我們確定在viewDidLoad中會(huì)初始化棚辽,并且在ViewController的生命周期內(nèi)不會(huì)置為nil,但是在對myLabel操作時(shí)冰肴,每次依然要加上!來強(qiáng)制拆包(在讀取值的時(shí)候屈藐,也可以用?,謝謝iPresent在回復(fù)中提醒)熙尉,比如:
myLabel!.text = "text"
myLabel!.frame = CGRectMake(0, 0, 10, 10)
...
對于這種類型的值联逻,我們可以直接這么聲明:var myLabel: UILabel!, 果然是高(hao)大(gui)上(yi)的語法!, 這種是特殊的Optional,稱為Implicitly Unwrapped Optionals, 直譯就是隱式拆包的Optional检痰,就等于說你每次對這種類型的值操作時(shí)包归,都會(huì)自動(dòng)在操作前補(bǔ)上一個(gè)!進(jìn)行拆包,然后在執(zhí)行后面的操作铅歼,當(dāng)然如果該值是nil公壤,也一樣會(huì)報(bào)錯(cuò)crash掉。
var myLabel: UILabel! //!相當(dāng)于下面這種寫法的語法糖
var myLabel: ImplicitlyUnwrappedOptional<UILabel>
那么!大概也有兩種使用場景
1.強(qiáng)制對Optional值進(jìn)行拆包(unwrap)
2.聲明Implicitly Unwrapped Optionals值椎椰,一般用于類中的屬性
Swift是門新生的語言厦幅,我們有幸見證了它的誕生,激動(dòng)之余也在佩服蘋果大刀闊斧的推出一個(gè)新的語言替代一個(gè)已經(jīng)比較成熟語言的魄力慨飘,今天在知乎日報(bào)上看到一個(gè)回答是說Swift是一門玩具語言确憨,正當(dāng)想去吐槽,發(fā)現(xiàn)回答已經(jīng)被刪除了。個(gè)人認(rèn)為蘋果是很認(rèn)真的推出Swift的缚态,從Swift的各種細(xì)微的設(shè)計(jì)也能看的出來磁椒。
另外這兩個(gè)小符號(hào)就花費(fèi)了我不少的時(shí)間來理解,可能依然會(huì)有錯(cuò)誤和不妥之處玫芦,歡迎大家指正浆熔,本文旨在拋磚引玉。除此之外桥帆,Swift還有很多很棒的特性医增,WWDC 2014 會(huì)有四五個(gè)和Swift語言相關(guān)的Video,大家也可以去關(guān)注一下老虫。