? ? 最近公司項(xiàng)目開始用swift寫香到,自己也開始學(xué)習(xí),畢竟蘋果出這個(gè)語言,是準(zhǔn)備以后會替代OC的悠就。
在對于使用千绪? !時(shí)自己感到很困惑梗脾,怎么區(qū)分荸型?。炸茧。瑞妇。。梭冠。
辕狰? 有可能為nil ? ? !一定為非nil ?帶著疑慮 開始探索控漠。柳琢。。润脸。柬脸。。
Swift語言使用var定義變量毙驯,但和別的語言不同倒堕,Swift里不會自動給變量賦初始值,也就是說變量不會有默認(rèn)值爆价,所以要求使用變量之前必須要對其初始化垦巴。如果在使用變量之前不進(jìn)行初始化就會報(bào)錯(cuò):
var stringValue : String
//error: variable 'stringValue' used before being initialized
//let hashValue = stringValue.hashValue
let hashValue = stringValue.hashValue
? ?上面了解到的是普通值,接下來Optional值要上場了铭段,Optional其實(shí)是個(gè)enum骤宣,里面有None和Some兩種類型。其實(shí)所謂的nil就是Optional.None, 非nil就是Optional.Some, 然后會通過Some(T)包裝(wrap)原始值序愚,這也是為什么在使用Optional的時(shí)候要拆包(從enum里取出來原始值)的原因, 也是PlayGround會把Optional值顯示為類似{Some "hello world"}的原因憔披,這里是enum Optional的定義:
enum Optional: 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(f: (T) -> U) -> U?
func getMirror() -> Mirror
}
聲明為Optional只需要在類型后面緊跟一個(gè)?即可。如:
var strValue: String?//?相當(dāng)于下面這種寫法的語法糖
var strValue: Optional
上面這個(gè)Optional的聲明爸吮,意思不是”我聲明了一個(gè)Optional的String值”, 而是”我聲明了一個(gè)Optional類型值芬膝,它可能包含一個(gè)String值,也可能什么都不包含”形娇,也就是說實(shí)際上我們聲明的是Optional類型锰霜,而 不是聲明了一個(gè)String類型,這一點(diǎn)需要銘記在心桐早。
一旦聲明為Optional的癣缅,如果不顯式的賦值就會有個(gè)默認(rèn)值nil厨剪。判斷一個(gè)Optional的值是否有值,可以用if來判斷:
ifstrValue {
//do sth with strValue
}
然后怎么使用Optional值呢友存?文檔中也有提到說祷膳,在使用Optional值的時(shí)候需要在具體的操作,比如調(diào)用方法爬立、屬性钾唬、下標(biāo)索引等前面需要加上一個(gè)?万哪,如果是nil值侠驯,也就是Optional.None,會跳過后面的操作不執(zhí)行奕巍,如果有值吟策,就是Optional.Some,可能就會拆包(unwrap)的止,然后對拆包后的值執(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ù)括號前加上一個(gè)?的方式來安全地調(diào)用protocol的optional方法崩溪。
另外如果你需要像下面這樣向下轉(zhuǎn)型(Downcast)浅役,可能會用到as?:
iflet dataSource =objectas?UITableViewDataSource {
let rowsInFirstSection= dataSource.tableView(tableView, numberOfRowsInSection:0)
}
? ? 的幾種使用場景:
1.聲明Optional值變量
2.用在對Optional值操作中,用來判斷是否能響應(yīng)后面的操作
3.用于安全調(diào)用protocol的optional方法
4.使用 as? 向下轉(zhuǎn)型(Downcast)
直接上例子伶唯,strValue是Optional的String:
let hashValue = strValue!.hashValue 這里的!表示“我確定這里的的strValue一定是非nil的觉既,盡情調(diào)用吧” ,比如這種情況:
ifstrValue { ??let hashValue= strValue!.hashValue ?}
{}里的strValue一定是非nil的乳幸,所以就能直接加上!奋救,強(qiáng)制拆包(unwrap)并執(zhí)行后面的操作。 當(dāng)然如果不加判斷反惕,strValue不小心為nil的話尝艘,就會出錯(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中會初始化盾戴,并且在ViewController的生命周期內(nèi)不會置為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í)畏梆,都會自動在操作前補(bǔ)上一個(gè)!進(jìn)行拆包您宪,然后在執(zhí)行后面的操作,當(dāng)然如果該值是nil奠涌,也一樣會報(bào)錯(cuò)crash掉宪巨。
varmyLabel:UILabel!//!相當(dāng)于下面這種寫法的語法糖varmyLabel:ImplicitlyUnwrappedOptional
! ?大概也有兩種使用場景
1.強(qiáng)制對Optional值進(jìn)行拆包(unwrap)
2.聲明Implicitly Unwrapped Optionals值,一般用于類中的屬性