05-可選項(xiàng)

可選項(xiàng)(Optional)

  • 可選項(xiàng)误债,一般也叫可選類型浸船,它允許將值設(shè)置為nil

  • 在類型名稱后面加個(gè)問(wèn)號(hào)? 來(lái)定義一個(gè)可選項(xiàng)

var name: String? = "Jack" 
name = nil  
var age: Int? // 默認(rèn)就是nil 
age = 10
age = nil 
var array = [1, 15, 40, 29] 
func get(_ index: Int) -> Int? {
  if index < 0 || index >= array.count {
    return nil  
  }  
  return array[index] 
} 

print(get(1))  // Optional(15) 
print(get(-1)) // nil 
print(get(4))  // nil 

強(qiáng)制解包 (Forced Unwrapping)

  • 可選項(xiàng)是對(duì)其他類型的一層包裝,可以將它理解為一個(gè)盒子

  • 如果為nil寝蹈,那么它是個(gè)空盒子

  • 如果不為nil李命,那么盒子里裝的是:被包裝類型的數(shù)據(jù)

var age: Int? // 默認(rèn)就是nil 
age = 10
age = nil                                                 
image.png
  • 如果要從可選項(xiàng)中取出被包裝的數(shù)據(jù)(將盒子里裝的東西取出來(lái)),需要使用感嘆號(hào)! 進(jìn)行強(qiáng)制解包
var age: Int? = 10
let ageInt: Int = age!
ageInt += 10
  • 如果對(duì)值為nil的可選項(xiàng)(空盒子)進(jìn)行強(qiáng)制解包箫老,將會(huì)產(chǎn)生運(yùn)行時(shí)錯(cuò)誤
var age: Int? 
age!

Fatal error: Unexpectedly found nil while unwrapping an Optional value 

判斷可選項(xiàng)是否包含值

let number = Int("123") 
if number != nil {
  print("字符串轉(zhuǎn)換整數(shù)成功:\(number!)") 
} else {
  print("字符串轉(zhuǎn)換整數(shù)失敗") 
}  
// 字符串轉(zhuǎn)換整數(shù)成功:123

可選項(xiàng)綁定 (Optional Binding)

  • 可以使用可選項(xiàng)綁定來(lái)判斷可選項(xiàng)是否包含值

  • 如果包含就自動(dòng)解包封字,把值賦給一個(gè)臨時(shí)的常量(let)或者變量(var),并返回true耍鬓,否則返回false

if let number = Int("123") {
 print("字符串轉(zhuǎn)換整數(shù)成功:\(number)") 
 // number是強(qiáng)制解包之后的Int值
 // number作用域僅限于這個(gè)大括號(hào)  
 } else {
  print("字符串轉(zhuǎn)換整數(shù)失敗")  
 }  
 // 字符串轉(zhuǎn)換整數(shù)成功:123
 enum Season : Int {
   case spring = 1, summer, autumn, winter 
 } 

 if let season = Season(rawValue: 6) {
   switch season {
     case .spring:  
     print("the season is spring")  
     default:  
     print("the season is other") 
   } 
 } else {
   print("no such season")  
 } 
 // no such season 

等價(jià)寫法

if let first = Int("4") {
  if let second = Int("42") {
    if first < second && second < 100 {
      print("\(first) < \(second) < 100")  
    } 
  }  
}  
// 4 < 42 < 100 

if let first = Int("4"),  
    let second = Int("42"), 
    first < second && second < 100 {
  print("\(second) < \(second) < 100")  
}  
// 4 < 42 < 100 

while循環(huán)中使用可選項(xiàng)綁定

// 遍歷數(shù)組阔籽,將遇到的正數(shù)都加起來(lái),如果遇到負(fù)數(shù)或者非數(shù)字牲蜀,停止遍歷 
var strs = ["10", "20", "abc", "-20", "30"] 

var index = 0
var sum = 0
while let num = Int(strs[index]), num > 0 {
  sum += num  index += 1
}  
print(sum) 

空合并運(yùn)算符 (Nil - Coalescing Operator)

public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T?) rethrows -> T? 
public func ?? <T>(optional: T?, defaultValue: @autoclosure () throws -> T) rethrows -> T  
  • a ?? b

  • a 是可選項(xiàng)

  • b 是可選項(xiàng) 或者 不是可選項(xiàng)

  • b 跟 a 的存儲(chǔ)類型必須相同

  • 如果 a 不為nil笆制,就返回 a

  • 如果 a 為nil,就返回 b

  • 如果 b 不是可選項(xiàng)涣达,返回 a 時(shí)會(huì)自動(dòng)解包

 let a: Int? = 1
 let b: Int? = 2
 let c = a ?? b // c是Int? , Optional(1)  

 // a有值,返回a
 let a: Int? = nil
 let b: Int? = 2
 let c = a ?? b // c是Int? , Optional(2)  

 // a無(wú)值在辆,返回b
 let a: Int? = nil
 let b: Int? = nil
 let c = a ?? b // c是Int? , nil 

 // a無(wú)值证薇,返回b
 let a: Int? = 1
 let b: Int = 2
 let c = a ?? b // c是Int , 1  

 // a有值,返回a匆篓,但是b是int浑度,自動(dòng)解包
 let a: Int? = nil
 let b: Int = 2
 let c = a ?? b // c是Int , 2  

 // a有值,返回a鸦概,b是int箩张,自動(dòng)解包
 // 如果不使用??運(yùn)算符 
 let a: Int? = nil 
 let b: Int = 2
 let c: Int 
 if let tmp = a {
   c = tmp  
 } else {
  c=b  
 }  

多個(gè) ?? 一起使用

let a: Int? = 1
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 1

let a: Int? = nil
let b: Int? = 2
let c = a ?? b ?? 3 // c是Int , 2

let a: Int? = nil
let b: Int? = nil
let c = a ?? b ?? 3 // c是Int , 3

?? 跟 if let 配合使用

let a: Int? = nil 
let b: Int? = 2
if let c = a ?? b {
  print(c) 
}  
// 類似于if a != nil || b != nil 

if let c = a, let d = b {
  print(c)  
  print(d) 
}  
// 類似于if a != nil && b != nil 

if語(yǔ)句實(shí)現(xiàn)登錄

func login (_ info: [String : String]) {
    let username: String
    if let tmp = info["username"] {
        username = tmp
    } else {
        print("請(qǐng)輸入用戶名")
        return
    }

    let password: String
    if let tmp = info["password"] {
        password = tmp
    } else {
        print("請(qǐng)輸入密碼")
        return
    }

    // if username ....
    // if password ....
    print("用戶名:\(username)", "密碼:\(password)", "登錄ing")
}

login(["username" : "jack", "password" : "123456"] ) 
login(["username" : "jack")     // 請(qǐng)輸入密碼
login(["password" : "123456"] ) // 請(qǐng)輸入用戶名

guard語(yǔ)句

 guard 條件 esle {
     // do something....
     退出當(dāng)前作用域
     // return break continue throw error
 }
  • 當(dāng)guard語(yǔ)句的條件為false時(shí),就會(huì)執(zhí)行大括號(hào)里面的代碼

  • 當(dāng)guard語(yǔ)句的條件為true時(shí)窗市,就會(huì)跳過(guò)guard語(yǔ)句

  • guard語(yǔ)句特別合適用來(lái) “提前退出”

  • 當(dāng)使用guard語(yǔ)句進(jìn)行可選項(xiàng)綁定時(shí)先慷,綁定的常量(let、變量(var)也能在外層作用域中使用

func login (_ info: [String : String]) {
    guard let username = info["username"] else {
        print("請(qǐng)輸入用戶名")
        return
    }

    guard let password = info["password"] else {
        print("請(qǐng)輸入密碼")
        return
    }

    // if username ....
    // if password ....
    print("用戶名:\(username)", "密碼:\(password)", "登錄ing")
}

隱式解包( Implicitly Unwrapped Optional)

  • 在某些情況下谨设,可選項(xiàng)一旦被設(shè)定值之后熟掂,就會(huì)一直擁有值

  • 在這種情況下,可以去掉檢查扎拣,也不必每次訪問(wèn)的時(shí)候都進(jìn)行解包,因?yàn)樗艽_定每次訪問(wèn)的時(shí)候都有值

  • 可以在類型后面加個(gè)感嘆號(hào) ! 定義一個(gè)隱式解包的可選項(xiàng)

 let num1: Int! = 10
 let num2: Int = num1 
 if num1 != nil {
   print(num1 + 6) // 16 
 } 
 if let num3 = num1 {
   print(num3)  
 } 

 let num1: Int! = nil 
 // Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value 
 let num2: Int = num1 

字符串插值

  • 可選項(xiàng)在字符串插值或者直接打印時(shí)素跺,編譯器會(huì)發(fā)出警告
var age: Int? = 10print("My age is \(age)") 
  • 至少有3種方法消除警告
print("My age is \(age!)")
// My age is 10 

print("My age is \(String(describing: age))") 
// My age is Optional(10) 

print("My age is \(age ?? 0)") 
// My age is 10 

多重可選項(xiàng)

var num1: Int? = 10
var num2: Int?? = num1 
var num3: Int?? = 10 
image.png
// num2和num3是等效的
print(num2 == num3) // true 二蓝、
image.png
  • 可以使用lldb指令 frame variable –R 或者 fr v –R 查看區(qū)別 不能是playground
image.png
  • 空盒子none之后的大括號(hào)就不用看了
image.png
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市指厌,隨后出現(xiàn)的幾起案子刊愚,更是在濱河造成了極大的恐慌,老刑警劉巖踩验,帶你破解...
    沈念sama閱讀 206,013評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鸥诽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡箕憾,警方通過(guò)查閱死者的電腦和手機(jī)牡借,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)袭异,“玉大人钠龙,你說(shuō)我怎么就攤上這事∮澹” “怎么了碴里?”我有些...
    開(kāi)封第一講書人閱讀 152,370評(píng)論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)上真。 經(jīng)常有香客問(wèn)我咬腋,道長(zhǎng),這世上最難降的妖魔是什么睡互? 我笑而不...
    開(kāi)封第一講書人閱讀 55,168評(píng)論 1 278
  • 正文 為了忘掉前任根竿,我火速辦了婚禮溜徙,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘犀填。我一直安慰自己蠢壹,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,153評(píng)論 5 371
  • 文/花漫 我一把揭開(kāi)白布九巡。 她就那樣靜靜地躺著图贸,像睡著了一般。 火紅的嫁衣襯著肌膚如雪冕广。 梳的紋絲不亂的頭發(fā)上疏日,一...
    開(kāi)封第一講書人閱讀 48,954評(píng)論 1 283
  • 那天,我揣著相機(jī)與錄音撒汉,去河邊找鬼沟优。 笑死,一個(gè)胖子當(dāng)著我的面吹牛睬辐,可吹牛的內(nèi)容都是我干的挠阁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,271評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼溯饵,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼侵俗!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起丰刊,我...
    開(kāi)封第一講書人閱讀 36,916評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤隘谣,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后啄巧,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體寻歧,經(jīng)...
    沈念sama閱讀 43,382評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,877評(píng)論 2 323
  • 正文 我和宋清朗相戀三年秩仆,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了码泛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 37,989評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逗概,死狀恐怖弟晚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情逾苫,我是刑警寧澤卿城,帶...
    沈念sama閱讀 33,624評(píng)論 4 322
  • 正文 年R本政府宣布,位于F島的核電站铅搓,受9級(jí)特大地震影響瑟押,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜星掰,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,209評(píng)論 3 307
  • 文/蒙蒙 一多望、第九天 我趴在偏房一處隱蔽的房頂上張望嫩舟。 院中可真熱鬧,春花似錦怀偷、人聲如沸家厌。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 30,199評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)饭于。三九已至,卻和暖如春维蒙,著一層夾襖步出監(jiān)牢的瞬間掰吕,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 31,418評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工颅痊, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留殖熟,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,401評(píng)論 2 352
  • 正文 我出身青樓斑响,卻偏偏與公主長(zhǎng)得像菱属,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子恋捆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,700評(píng)論 2 345

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

  • 可選項(xiàng)(Optional) 強(qiáng)制解包(Forced Unwrapping) 判斷可選項(xiàng)是否包含值 可選項(xiàng)綁定(Op...
    SwordDevil閱讀 333評(píng)論 0 1
  • 作者: Liwx 郵箱: 1032282633@qq.com 源碼: 需要源碼的同學(xué), 可以在評(píng)論區(qū)留下您的郵箱 ...
    Liwx閱讀 6,098評(píng)論 2 8
  • 一:枚舉 枚舉的定義Swift中的枚舉定義枚舉類型很簡(jiǎn)單: 同 OC不同的是,Swift中的枚舉不單單可以是Int...
    小心韓國(guó)人閱讀 389評(píng)論 0 1
  • 一. 可選項(xiàng)的基本使用 可選項(xiàng)照皆,一般也叫可選類型,它允許將值設(shè)置為nil沸停。在類型名稱后面加個(gè)問(wèn)號(hào) ? 來(lái)定義一個(gè)可...
    Imkata閱讀 758評(píng)論 0 1
  • 隨著swift語(yǔ)言的不斷發(fā)展,越來(lái)越來(lái)趨于穩(wěn)定化≌炎浚現(xiàn)在也有很多公司使用swift來(lái)開(kāi)發(fā)新的App愤钾,那么不會(huì)swif...
    木子雨廷t閱讀 829評(píng)論 0 0