swift中問號(hào)?和嘆號(hào)!理解

參考鏈接:http://blog.csdn.net/zhouleizhao/article/details/40619189

語(yǔ)言使用var定義變量,但和別的語(yǔ)言不同,Swift里不會(huì)自動(dòng)給變量賦初始值畅哑,也就是說變量不會(huì)有默認(rèn)值,所以要求使用變量之前必須要對(duì)其初始化勋陪。如果在使用變量之前不進(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值要上場(chǎng)了。經(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)于下面這種寫法的語(yǔ)法糖
var strValue: Optional<String>

上面這個(gè)Optional的聲明袱饭,意思不是”我聲明了一個(gè)Optional的String值”, 而是”我聲明了一個(gè)Optional類型值川无,它可能包含一個(gè)String值,也可能什么都不包含”虑乖,也就是說實(shí)際上我們聲明的是Optional類型懦趋,而不是聲明了一個(gè)String類型,這一點(diǎn)需要銘記在心疹味。

建議再讀一遍上段文字仅叫。

一旦聲明為Optional的,如果不顯式的賦值就會(huì)有個(gè)默認(rèn)值nil佛猛。判斷一個(gè)Optional的值是否有值惑芭,可以用if來判斷:

if strValue 
{ 
//do sth with strValue
}

然后怎么使用Optional值呢?文檔中也有提到說继找,在使用Optional值的時(shí)候需要在具體的操作遂跟,比如調(diào)用方法、屬性婴渡、下標(biāo)索引等前面需要加上一個(gè)?
幻锁,如果是nil值,也就是Optional.None
边臼,會(huì)跳過后面的操作不執(zhí)行哄尔,如果有值,就是Optional.Some
柠并,可能就會(huì)拆包(unwrap)岭接,然后對(duì)拆包后的值執(zhí)行后面的操作富拗,來保證執(zhí)行這個(gè)操作的安全性,比如:

let hashValue = strValue?.hashValue

strValue是Optional的字符串鸣戴,如果strValue是nil啃沪,則hashValue也為nil,如果strValue不為nil窄锅,hashValue就是strValue字符串的哈希值(其實(shí)也是用Optional wrap后的值)
另外创千,?還可以用在安全地調(diào)用protocol類型方法上,比如:

@objc protocol Downloadable { 
@optional func download(toPath: String) -> Bool;
}
@objc class Content: Downloadable { 
//download method not be implemented
}
var delegate: Downloadable = Downloadable()
delegate.download?("some path")

因?yàn)樯厦娴膁elegate是Downloadable類型的入偷,它的download
方法是optional追驴,所以它的具體實(shí)現(xiàn)有沒有download
方法是不確定的。Swift提供了一種在參數(shù)括號(hào)前加上一個(gè)?
的方式來安全地調(diào)用protocol的optional方法疏之。
另外如果你需要像下面這樣向下轉(zhuǎn)型(Downcast)殿雪,可能會(huì)用到 as?

if let dataSource = object as? UITableViewDataSource 
{
 let rowsInFirstSection = dataSource.tableView(tableView, numberOfRowsInSection: 0)
}

到這里我們看到了?
的幾種使用場(chǎng)景:1.聲明Optional值變量2.用在對(duì)Optional值操作中,用來判斷是否能響應(yīng)后面的操作3.用于安全調(diào)用protocol的optional方法4.使用 as? 向下轉(zhuǎn)型(Downcast)

另外体捏,對(duì)于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)后才能得到原來值几缭,然后才能對(duì)其操作,那怎么來拆包呢沃呢?拆包提到了幾種方法年栓,一種是Optional Binding
, 比如:

if let str = strValue { 
let hashValue = str.hashValue
}

還有一種是在具體的操作前添加!
符號(hào)薄霜,好吧某抓,這又是什么詭異的語(yǔ)法?!
直接上例子,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,但是在對(duì)myLabel操作時(shí)第股,每次依然要加上!
來強(qiáng)制拆包(在讀取值的時(shí)候应民,也可以用?
,謝謝iPresent在回復(fù)中提醒)夕吻,比如:

myLabel!.text = "text"
myLabel!.frame = CGRectMake(0, 0, 10, 10)...

對(duì)于這種類型的值诲锹,我們可以直接這么聲明:var myLabel: UILabel!
, 果然是高(hao)大(gui)上(yi)的語(yǔ)法!, 這種是特殊的Optional,稱為Implicitly Unwrapped Optionals
, 直譯就是隱式拆包的Optional涉馅,就等于說你每次對(duì)這種類型的值操作時(shí)归园,都會(huì)自動(dòng)在操作前補(bǔ)上一個(gè)!
進(jìn)行拆包,然后在執(zhí)行后面的操作稚矿,當(dāng)然如果該值是nil庸诱,也一樣會(huì)報(bào)錯(cuò)crash掉。

var myLabel: UILabel! 
//!相當(dāng)于下面這種寫法的語(yǔ)法糖
var myLabel: ImplicitlyUnwrappedOptional<UILabel>

那么!
大概也有兩種使用場(chǎng)景1.強(qiáng)制對(duì)Optional值進(jìn)行拆包(unwrap)2.聲明Implicitly Unwrapped Optionals
值晤揣,一般用于類中的屬性

Swift是門新生的語(yǔ)言桥爽,我們有幸見證了它的誕生,激動(dòng)之余也在佩服蘋果大刀闊斧的推出一個(gè)新的語(yǔ)言替代一個(gè)已經(jīng)比較成熟語(yǔ)言的魄力昧识,今天在知乎日?qǐng)?bào)上看到一個(gè)回答是說Swift是一門玩具語(yǔ)言钠四,正當(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語(yǔ)言相關(guān)的Video煞檩,大家也可以去關(guān)注一下处嫌。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市斟湃,隨后出現(xiàn)的幾起案子熏迹,更是在濱河造成了極大的恐慌,老刑警劉巖凝赛,帶你破解...
    沈念sama閱讀 216,692評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件注暗,死亡現(xiàn)場(chǎng)離奇詭異坛缕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)捆昏,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門赚楚,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人骗卜,你說我怎么就攤上這事宠页。” “怎么了寇仓?”我有些...
    開封第一講書人閱讀 162,995評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵举户,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我遍烦,道長(zhǎng)俭嘁,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,223評(píng)論 1 292
  • 正文 為了忘掉前任服猪,我火速辦了婚禮供填,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘罢猪。我一直安慰自己近她,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評(píng)論 6 388
  • 文/花漫 我一把揭開白布坡脐。 她就那樣靜靜地躺著泄私,像睡著了一般。 火紅的嫁衣襯著肌膚如雪备闲。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評(píng)論 1 299
  • 那天捅暴,我揣著相機(jī)與錄音恬砂,去河邊找鬼。 笑死蓬痒,一個(gè)胖子當(dāng)著我的面吹牛泻骤,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播梧奢,決...
    沈念sama閱讀 40,091評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼狱掂,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了亲轨?” 一聲冷哼從身側(cè)響起趋惨,我...
    開封第一講書人閱讀 38,929評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎惦蚊,沒想到半個(gè)月后器虾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體讯嫂,經(jīng)...
    沈念sama閱讀 45,346評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評(píng)論 2 333
  • 正文 我和宋清朗相戀三年兆沙,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了欧芽。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,739評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡葛圃,死狀恐怖千扔,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情库正,我是刑警寧澤昏鹃,帶...
    沈念sama閱讀 35,437評(píng)論 5 344
  • 正文 年R本政府宣布,位于F島的核電站诀诊,受9級(jí)特大地震影響洞渤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜属瓣,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評(píng)論 3 326
  • 文/蒙蒙 一载迄、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧抡蛙,春花似錦护昧、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至熊昌,卻和暖如春绽榛,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背婿屹。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工灭美, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人昂利。 一個(gè)月前我還...
    沈念sama閱讀 47,760評(píng)論 2 369
  • 正文 我出身青樓届腐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親蜂奸。 傳聞我的和親對(duì)象是個(gè)殘疾皇子犁苏,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Swift語(yǔ)言使用var定義變量,但和別的語(yǔ)言不同扩所,Swift里不會(huì)自動(dòng)給變量賦初始值围详,也就是說變量不會(huì)有默認(rèn)值,...
    默默的前行閱讀 2,366評(píng)論 5 2
  • 關(guān)于 Swift 重要這個(gè)文檔所包含的準(zhǔn)備信息, 是關(guān)于開發(fā)的 API 和技術(shù)的碌奉。這個(gè)信息可能會(huì)改變, 根據(jù)這個(gè)文...
    無(wú)灃閱讀 4,299評(píng)論 1 27
  • importUIKit classViewController:UITabBarController{ enumD...
    明哥_Young閱讀 3,802評(píng)論 1 10
  • Swift語(yǔ)言使用var定義變量短曾,但和別的語(yǔ)言不同寒砖,Swift里不會(huì)自動(dòng)給變量賦初始值,也就是說變量不會(huì)有默認(rèn)值嫉拐,...
    子鍵_北京不眠夜閱讀 207評(píng)論 0 0
  • Swift語(yǔ)言使用var定義變量哩都,但和別的語(yǔ)言不同,Swift里不會(huì)自動(dòng)給變量賦初始值婉徘,也就是說變量不會(huì)有默認(rèn)值漠嵌,...
    TomatosX閱讀 254評(píng)論 0 0