最近在學習swift,期間也看了不少教程和大神的博客,最後把筆記放這裏,方便查看複習~swift
附上學習資料地址:w3cschool-Swift 教程 、 YungFan大神的簡書(推薦看一下,有些知識點總結地簡直通俗易懂)數組
通俗一點來說,swift中的可選項與nil
有關。安全
由於swift是強類型語言,nil也是一個特殊類型,因此說其餘類型的數據不能直接賦值爲nil
markdown
若是遇到不肯定是否有值的類型,可使用可選項,那麼這個類型只能兩個取值:ni
或者 有一個肯定的值
app
常規寫法ide
var name: Optional<String>
複製代碼
經常使用語法糖的寫法oop
//注意:在類型和 ? 之間沒有空格
var name: String?
複製代碼
給可選類型賦值學習
//聲明一個可選項
var str: String? = nil
//賦值
str = "hello"
複製代碼
取值ui
print(str) //Optional("hello")
複製代碼
強制解包(!)取值url
//注意:這種作法不安全,只能用於 已經肯定str真的有值的狀況,不然會崩潰
print(str!) //hello
複製代碼
強制解包安全作法
if str != nil {
print(str!) //hello
}
複製代碼
隱式解包
if let newStr = str {
//此時輸出的就是str的值,而不是Optional str
print(newStr) //hello
}else{
print("這個值是nil")
}
複製代碼
守衛語句解包
//判斷當語句=false,也就是newStr = nil,直接執行return,也有效防止了崩潰
guard let newStr = str else{
return
}
print(newStr)
複製代碼
用可選項來接收URL,讓代碼更加嚴謹
// 正確寫法:使用可選類型來接收
let url : URL? = URL(string: "https://www.baidu.com")
// 也能夠這麼寫:該方式利用類型推斷
let url1 = URL(string: "https://www.baidu.com")
// 經過url來建立request對象:在使用可選類型前要先進行判斷是否有值
// 該語法成爲可選綁定(若是url有值就解包賦值給tempURL,而且執行{})
if let tempUrl = url {
let request = URLRequest(url: tempUrl)
}
複製代碼
/*
主要做用於值缺失的狀況,相似oc中某個對象=nil,在swift中只有可選項的常量或者變量才能使用nil
可選項的標誌:?
nil:
oc中,表示一個指向不存在對象的指針
swift中,表示一種特殊類型,值缺失(不只僅對象類型,任何類型的可選項都能置爲nil)
*/
var code: Int? = 100
code = nil
/*
var name: Int = 1000
name = nil
這種狀況會報錯,不是可選項
*/
/*
使用感嘆號:!
一旦咱們知道可選項確定有一個值,那麼爲了拿到這個值,就要在可選項以後加上"!"來取值
*/
var age: Int? = 18
print("可選項確定有一個值:\(age!)")
複製代碼
可選鏈 (Optional Chaining)
是一種能夠請求和調用屬性、方法和子腳本的過程,用於請求或調用的目標可能爲nil。
可選鏈返回兩個值:
屢次請求或調用能夠被連接成一個鏈,若是任意一個節點爲nil將致使整條鏈失效。
經過在屬性、方法、或下標腳本的可選值後面放一個問號(?),便可定義一個可選鏈。
使用可選鏈'?'
: 將'?'放在可選值後面來調用方法、屬性、下標腳本,當可選爲nil的時候 輸出比較友好的錯誤信息
使用強制解析'!'
: 將'!'放在可選值後面來調用方法、屬性、下標腳本,用於強制展開值,當可選爲nil的時候 強制展開會執行錯誤
代碼示例:
class Residence {
var numberOfRooms = 1
}
class Person {
var residence: Residence?
}
let john = Person()
// ! 將致使運行時錯誤 :Fatal error: Unexpectedly found nil while unwrapping an Optional value (致命錯誤:在展開可選值時意外發現nil)
let roomCount = john.residence!.numberOfRooms
// ?連接可選residence?屬性,若是residence存在則取回numberOfRooms的值
if let roomCount = john.residence?.numberOfRooms {
print("John 的房間號爲 \(roomCount)。")
} else {
print("不能查看房間號")
}
打印:不能查看房間號
複製代碼
首先定義了4個類,包含了一個多層可選鏈
class Person {
//住宅
var residence: Residence?
}
class Residence {
// 定義了一個變量 rooms,它被初始化爲一個Room[]類型的空數組
var rooms = [Room]()
var numberOfRooms: Int {
return rooms.count
}
subscript(i: Int) -> Room {
return rooms[i]
}
func printNumberOfRooms() {
print("房間號爲 \(numberOfRooms)")
}
var address: Address?
}
// Room 定義一個name屬性和一個設定room名的初始化器
class Room {
let name: String
init(name: String) { self.name = name }
}
// 模型中的最終類叫作Address
class Address {
//建築名
var buildingName: String?
//建築號
var buildingNumber: String?
//街道
var street: String?
func buildingIdentifier() -> String? {
if (buildingName != nil) {
return buildingName
} else if (buildingNumber != nil) {
return buildingNumber
} else {
return nil
}
}
}
複製代碼
let john = Person()
if john.residence?.printNumberOfRooms() != nil {
print("輸出房間號")
} else {
print("沒法輸出房間號")
}
打印:沒法輸出房間號
複製代碼
咱們能夠經過可選鏈來獲取下標腳本的值,可是不能經過可選鏈來設置下標腳本
let john = Person()
//?在這個位置的緣由是:john.residence 是可選鏈試圖得到的可選值
if let firstRoomName = john.residence?[0].name {
print("第一個房間名 \(firstRoomName).")
} else {
print("沒法檢索到房間")
}
複製代碼
再來看看給 john 賦個值
let john = Person()
let johnsHouse = Residence()
johnsHouse.rooms.append(Room(name: "客廳"))
johnsHouse.rooms.append(Room(name: "廚房"))
john.residence = johnsHouse
let johnsAddress = Address()
johnsAddress.buildingName = "A123"
johnsAddress.street = "A123 Street"
john.residence!.address = johnsAddress
//獲取下標腳本
if let firstRoomName = john.residence?[0].name {
print("第一個房間名爲\(firstRoomName)")
} else {
print("沒法檢索到房間")
}
//打印:第一個房間名爲客廳
//兩層可選鏈
if let johnsStreet = john.residence?.address?.street {
print("John 所在的街道是 \(johnsStreet)。")
} else {
print("沒法檢索到地址。 ")
}
//打印:John 所在的街道是 A123 Street
複製代碼