Swift 可選類型

對于使用Objective-C開發(fā)iOS的程序員來說,對象是否為nil在編寫程序的過程中程序員不太關(guān)心,直接使用就可以,在一些需要判斷的地方在判斷敛腌,當轉(zhuǎn)為Swift開發(fā)時,首先頭疼的問題就是可選類型,到底何時使用迎瞧?夸溶,何時使用!總是拿不太準凶硅,下面就詳細的講解一下

一缝裁、什么是可選類型

可選類型伴隨著Swift誕生,在原有的Objective-C語言中不存在足绅,究其原因捷绑,是因為Swift是類型安全的語言,而OC則是弱類型語言氢妈,OC中 str字符串既可以是nil粹污,也可以是字符串,而Swift中首量,這兩種狀態(tài)是不能同時存在的壮吩。
OC和Swift對于nil的解釋也是不太一樣的

1.Objective-C中的nil:表示缺少一個合法的對象,是指向不存在對象的指針加缘,對結(jié)構(gòu)體鸭叙、枚舉等類型不起作用(會返回NSNotFound)
2.Swift中的nil:表示任意類型的值缺失,是一個確定的值拣宏,要么是該類型的一個值要么什么都沒有(即為nil)

在Swift中Optional(可選類型)是一個含有兩種情況的枚舉沈贝,None 和 Some(T),用來表示可能有或可能沒有值勋乾。任何類型都可以明確聲明為(或者隱式轉(zhuǎn)換)可選類型宋下。當聲明一個可選類型的時候,要確保用括號給 ? 操作符一個合適的范圍辑莫。

1.1可選類型的聲明
var optionalStr: String? = "swift語言可選類型"http://聲明可選類型字符串学歧,并賦初值
var opStu:Student? //聲明可選opStu對象,賦初值nil

注意:在類型和 ?之間沒有空格

1.2 強制解析(拆包)

當你確定自定義的可選類型一定有值時各吨,可以使用操作符(!)進行強制解析枝笨,拿到數(shù)據(jù),嘆號表示"我知道一定有值绅你,請使用它",但是當你判斷錯誤,可選值為nil時使用(!)進行強制解析昭躺,會有運行錯誤忌锯。

var myStr:String? = nil
myStr="強制解析,一定有值"
if myStr != nil {
    print(myStr!)//使用领炫!進行強制解析
}else{
    print("字符串為nil")
}

運行結(jié)果

強制解析偶垮,一定有值
1.3 自動解析

在最初的聲明時使用?修飾,當你希望它自動解析是可以用似舵!代替脚猾?來修飾,這樣在變量使用時就不需要加砚哗!來強制拆包龙助,它會自動解析。

var myStr:String! //使用蛛芥!修飾
myStr="自動解析"
if myStr != nil {
    print(myStr)
}else{
    print("字符串為nil")
}

運行結(jié)果

自動解析
1.4 可選綁定

A.使用可選綁定提鸟,擺脫了頻繁的判斷是否為nil在賦值,但是使用可選綁定(optional binding)來判斷可選類型是否包含值仅淑,如果包含就把值賦給一個臨時常量或者變量称勋。可選綁定可以用在if和while語句中來對可選類型的值進行判斷并把值賦給一個常量或者變量涯竟。
格式:

if let tempStr = someOptional{
    tempStr//如果someOptiona有值的話赡鲜,就會賦值給tempStr,然后使用
}
var myStr:String?
myStr="可選綁定"
if  let tempStr = myStr {
    print(tempStr)
}else{
    print("字符串為nil")
}

運行結(jié)果

可選綁定

B.在可選類型判斷中還有g(shù)uard let的用法庐船,guard名為守衛(wèi)的意思银酬。guard let和if let剛好相反,guard let守護一定有值醉鳖。如果沒有捡硅,直接返回

let name: String? = "張三"
let age: Int? = 10

guard let nameNew = name,
      let ageNew = age
else {
        print("姓名 或 年齡 為nil")
        return
}

print("姓名 或 年齡 為\(name),\(age)")//運行到這里是一定有值的
1.5 as! 與 as? 的類型轉(zhuǎn)換

在寫Swift代碼時總是拿不準到底使用哪個,有時會根據(jù)編輯器的提示去Fix盗棵,但是這樣不能很好的解決問題壮韭。
1.as!使用場合

向下轉(zhuǎn)型(Downcasting)時使用。由于是強制類型轉(zhuǎn)換纹因,如果轉(zhuǎn)換失敗會報 runtime 運行錯誤喷屋。就是說強制從父類轉(zhuǎn)換成子類

class Animal {}
class Cat: Animal {}
let animal :Animal  = Cat()
let cat = animal as! Cat

2.as?使用場合

as? 和 as! 操作符的轉(zhuǎn)換規(guī)則完全一樣。但 as? 如果轉(zhuǎn)換不成功的時候便會返回一個 nil 對象瞭恰。成功的話返回可選類型值(optional)屯曹,需要我們拆包使用。由于 as? 在轉(zhuǎn)換失敗的時候也不會出現(xiàn)錯誤惊畏,所以對于如果能確保100%會成功的轉(zhuǎn)換則可使用 as!恶耽,否則使用 as?

let animal:Animal = Cat()

if let cat = animal as? Cat{
    print("cat is not nil")
} else {
    print("cat is nil")
}

二、可選類型的使用場景

2.1 函數(shù)或方法的返回類型為可選類型

在方法中返回值如Int?颜启、String?偷俭、(Int, String)?、[Int]?缰盏、[Int: String]?等

func returnOptionValue(value: Bool) -> String? { // 返回類型為可選String類型
    if value {
        return "返回類型是可選類型值" // 如果為真涌萤,返回Int類型的值1
    } else {
        return nil //返回nil
    }
}

let optionValue = returnOptionValue(value: true) // 要用可選綁定判斷再使用淹遵,因為returnOptionValue為String?可選類型
if let value = optionValue {
    print(value)
} else {
    print("none value")
}

運行結(jié)果

返回類型是可選類型值

返回類型為閉包可選

func returnOptionalFunc(value: Bool) -> (() -> (Void))? { // 返回類型為可選類型的閉包
    if value {
        return { () in
            print("返回類型是可選類型閉包")
        }
    } else {
        return nil
    }
}

let possibleFunc = returnOptionalFunc(value: true) // 要用可選綁定判斷再使用负溪,因為possibleFunc 為可選類型的閉包透揣,類型為() -> (Void)
if let aFunc = possibleFunc {
    print(aFunc())  // 注意增加()調(diào)用閉包,因為沒有參數(shù)則是空括號
} else {
    print("none func")
}

運行結(jié)果

返回類型是可選類型閉包
2.2 可選類型在類或結(jié)構(gòu)體中的運用

可選類型在類中的使用

class PossibleClass {
    var someValue: Int
    var possibleValue: String? // 可選存儲屬性川抡,默認值為nil
    init(someValue: Int) { // 構(gòu)造方法中可以不對possibleValue屬性初始化
        self.someValue = someValue
    }
}

let someClass = PossibleClass(someValue: 4)

可選類型在結(jié)構(gòu)體中的運用

struct PossibleStruct {
    var someValue: Int
    var possibleValue: String? // 可選存儲屬性辐真,默認值為nil
    // 結(jié)構(gòu)體中可以自定義一個init構(gòu)造器對屬性初始化,也可以不自定義
}

let someStruct = PossibleStruct(someValue: 4, possibleValue: nil)
2.3 可選類型在構(gòu)造器中使用
class PossibleStructInit {
    let someValue: String
    init?(someValue: String) { // 可失敗構(gòu)造器
        if someValue.isEmpty { return nil } // 如果實例化為空串猖腕,則返回nil(即實例化失敗)
        self.someValue = someValue
    }
}

let oneStruct = PossibleStructInit(someValue: "構(gòu)造器中使用") // abc不是空串拆祈,oneStruct為PossibleStructInit?可選類型
if let one = oneStruct { // 使用if let可選綁定判斷
    print(one.someValue)
} else {
    print("none value")
}
//輸入結(jié)果為:構(gòu)造器中使用

let twoStruct = PossibleStructInit(someValue: "") // 傳參為空串
if let two = twoStruct {
    print(two.someValue)
} else {
    print("none value")
}
//輸入結(jié)果為:none value
2.4 可選類型在錯誤處理中使用(try!與try?)

1.try?會將錯誤轉(zhuǎn)換為可選值倘感,當調(diào)用try?+函數(shù)或方法語句時候放坏,如果函數(shù)或方法拋出錯誤,程序不會發(fā)崩潰老玛,而返回一個nil淤年,如果沒有拋出錯誤則返回可選值。
2.使用try!可以打破錯誤傳播鏈條蜡豹。錯誤拋出后傳播給它的調(diào)用者麸粮,這樣就形成了一個傳播鏈條,但有的時候確實不想讓錯誤傳播下去镜廉,可以使用try!語句

let photo = try! loadImage(atPath: "./Resources/John Appleseed.jpg")
// 上述語句中在執(zhí)行l(wèi)oadImage方法時如果執(zhí)行失敗弄诲,使用try!來禁用錯誤傳遞,會有運行錯誤導致App崩潰
func someThrowingFunction() throws -> Int {
    // ...
}

let x = try? someThrowingFunction() // x可能正常返回一個Int類型的值也有可能拋出一個錯誤異常娇唯,使用時對x用if let可選綁定判斷
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末齐遵,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子塔插,更是在濱河造成了極大的恐慌梗摇,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,509評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件想许,死亡現(xiàn)場離奇詭異伶授,居然都是意外死亡,警方通過查閱死者的電腦和手機流纹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,806評論 3 394
  • 文/潘曉璐 我一進店門糜烹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人漱凝,你說我怎么就攤上這事疮蹦。” “怎么了碉哑?”我有些...
    開封第一講書人閱讀 163,875評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長妆毕。 經(jīng)常有香客問我笛粘,道長,這世上最難降的妖魔是什么湿硝? 我笑而不...
    開封第一講書人閱讀 58,441評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮关斜,結(jié)果婚禮上示括,老公的妹妹穿的比我還像新娘。我一直安慰自己痢畜,他們只是感情好垛膝,可當我...
    茶點故事閱讀 67,488評論 6 392
  • 文/花漫 我一把揭開白布丁稀。 她就那樣靜靜地躺著吼拥,像睡著了一般线衫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枯跑,一...
    開封第一講書人閱讀 51,365評論 1 302
  • 那天,我揣著相機與錄音,去河邊找鬼百匆。 笑死呜投,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的纵东。 我是一名探鬼主播啥寇,決...
    沈念sama閱讀 40,190評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼偎球,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,062評論 0 276
  • 序言:老撾萬榮一對情侶失蹤褂痰,失蹤者是張志新(化名)和其女友劉穎亩进,沒想到半個月后匪蝙,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體逛球,經(jīng)...
    沈念sama閱讀 45,500評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡幸海,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,706評論 3 335
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了肝集。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片所刀。...
    茶點故事閱讀 39,834評論 1 347
  • 序言:一個原本活蹦亂跳的男人離奇死亡厕倍,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耸三,到底是詐尸還是另有隱情榜配,我是刑警寧澤,帶...
    沈念sama閱讀 35,559評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站膜廊,受9級特大地震影響匙瘪,放射性物質(zhì)發(fā)生泄漏铆铆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,167評論 3 328
  • 文/蒙蒙 一丹喻、第九天 我趴在偏房一處隱蔽的房頂上張望薄货。 院中可真熱鬧,春花似錦碍论、人聲如沸谅猾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,779評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽税娜。三九已至,卻和暖如春藏研,著一層夾襖步出監(jiān)牢的瞬間敬矩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,912評論 1 269
  • 我被黑心中介騙來泰國打工蠢挡, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留谤绳,地道東北人。 一個月前我還...
    沈念sama閱讀 47,958評論 2 370
  • 正文 我出身青樓袒哥,卻偏偏與公主長得像缩筛,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子堡称,可洞房花燭夜當晚...
    茶點故事閱讀 44,779評論 2 354

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