一歌径、 基本概念
- 變量,類型亲茅,初始化
var str: String
str = "Hello World"
str.uppercaseString
var str2: String = "Hello World2"
- 類型推斷沮脖,強(qiáng)類型
var str3 = "Hello World3"
- 可選類型,枚舉
//Optional<Sting>
var errorCodeString: String?
errorCodeString = "404"
errorCodeString = nil
- 強(qiáng)制解包發(fā)現(xiàn)為nil導(dǎo)致運(yùn)行時(shí)崩潰,不安全芯急!
let theError: String = errorCodeString!
- if 語(yǔ)句
if errorCodeString != nil {
let theError = errorCodeString!
}
- 可選綁定
if let theError = errorCodeString {
}
- 可選綁定嵌套,"Pyramid of Doom"
if let theError = errorCodeString {
if let errorCodeInteger = Int(theError) {
if errorCodeInteger == 404 {
print("\(theError): \(errorCodeInteger)")
}
}
}
- 簡(jiǎn)化驶俊,都不為nil時(shí)執(zhí)行娶耍。where相當(dāng)于if判斷語(yǔ)句
if let theError = errorCodeString, errorCodeInteger = Int(theError) where errorCodeInteger == 404 {
print("\(theError): \(errorCodeInteger)")
}
4 .隱式解包的可選 -- 不安全!
var errorCodeString2: String!
errorCodeString2 = "404"
errorCodeString2 = nil
- 如果為nil饼酿,導(dǎo)致運(yùn)行時(shí)崩潰,不安全榕酒!
let theError2: String = errorCodeString2
- 萬(wàn)能的 if, 可選綁定
if errorCodeString2 != nil {
let theError2: String = errorCodeString2
}
if let theError2 = errorCodeString2 {
print(theError2)
}
注意:
如果一個(gè)變量之后可能變成nil的話請(qǐng)不要使用隱式解包的可選類型。
如果你需要在變量的生命周期中判斷是否是nil的話故俐,請(qǐng)使用普通可選類型想鹰。
二、安全地使用可選值
- Swift 的可選類型可以?來(lái)表?可能缺失或是計(jì)算失敗的值药版。
let cities = ["Paris": 2241, "Madrid": 3165, "Amsterdam": 827, "Berlin": 3562]
let madridPopulation: Int? = cities["Madrid"]
if madridPopulation != nil {
print ("The population of Madrid is \(madridPopulation! * 1000)")
} else {
print ("Unknown city: Madrid")
}
- 可選綁定辑舷,可以讓你避免寫 ! 后綴。不再需要顯式地使?強(qiáng)制解包槽片。
if let madridPopulation = cities["Madrid"] {
print ("The population of Madrid is \(madridPopulation * 1000)")
} else {
print ("Unknown city: Madrid")
}
- 空合運(yùn)算符
let madridPopulationValue: Int
if madridPopulation != nil {
madridPopulationValue = madridPopulation!
} else {
madridPopulationValue = 1000
}
//a != nil ? a! : b
//a ?? b
let madridPopulationValue2 = madridPopulation != nil ? madridPopulation! : 1000
let madridPopulationValue3 = madridPopulation ?? 1000
// autoclosure 類型標(biāo)簽來(lái)避開(kāi)創(chuàng)建顯式閉包 myOptional ?? myDefaultValue -> myOptional ?? { myDefaultValue }
- 可選鏈
可選鏈?zhǔn)秸{(diào)用(Optional Chaining)是一種可以在當(dāng)前值可能為nil的可選值上請(qǐng)求和調(diào)用屬性何缓、方法及下標(biāo)的方法。如果可選值有值还栓,那么調(diào)用就會(huì)成功碌廓;如果可選值是nil,那么調(diào)用將返回nil剩盒。多個(gè)調(diào)用可以連接在一起形成一個(gè)調(diào)用鏈谷婆,如果其中任何一個(gè)節(jié)點(diǎn)為nil,整個(gè)調(diào)用鏈都會(huì)失敗辽聊,即返回nil纪挎。
struct Order {
let orderNumber: Int
let person: Person?
}
struct Person {
let name: String
let address: Address?
}
struct Address {
let streetName: String
let city : String
let state: String?
}
let order = Order(orderNumber: 1, person: nil)
// order.person!.address!.state!
if let myPerson = order.person {
if let myAddress = myPerson.address {
if let myState = myAddress.state {
}
}
}
- 使?問(wèn)號(hào)運(yùn)算符來(lái)嘗試對(duì)可選類型進(jìn)?解包。當(dāng)任意?個(gè)組成項(xiàng)失敗時(shí)身隐,整條語(yǔ)句鏈將返回 nil廷区。
if let myState = order.person?.address?.state {
print ("This order will be shipped to \(myState)")
} else {
print ("Unknown person, address, or state.")
}
- 分支上的可選值
- switch 語(yǔ)句
switch madridPopulation {
case 0?: print ("Nobody in Madrid")
case (1..<1000)?: print ("Less than a million in Madrid")
case .Some(let x): print ("\(x) people in Madrid")
case .None: print("We don't know about Madrid")
}
- guard 語(yǔ)句: 在當(dāng)?些條件不滿?時(shí),可以盡早退出當(dāng)前作?域,避免不必要的計(jì)算贾铝∠肚幔可以使??可選的 population 值,?嵌套 if let 語(yǔ)句時(shí)更簡(jiǎn)單埠帕。
func populationDescriptionForCity(city: String) -> String? {
guard city != "madrid" else { return nil }
if city == "madrid" {
return nil
}
guard let population = cities[city ] else { return nil }
return "The population of Madrid is \(population * 1000)"
if let population = cities[city ] {
return "The population of Madrid is \(population * 1000)"
} else {
return nil
}
}
- 可選映射 : 若可選值存在,你可能會(huì)想操作它玖绿,否則返回 nil敛瓷。
madridPopulation.map { (<#Int#>) -> U in
}
madridPopulation.flatMap { (<#Int#>) -> U? in
}
let capitals = [
"France": "Paris",
"Spain": "Madrid",
"The Netherlands": "Amsterdam",
"Belgium": "Brussels"
]
func populationOfCapital(country: String) -> Int? {
guard let capital = capitals[country], population = cities[capital]
else { return nil }
return population * 1000
}
func populationOfCapital2(country: String) -> Int? {
return capitals[country].flatMap { capital in
cities [capital].flatMap { population in
return population * 1000
}
}
}
func populationOfCapital3(country: String) -> Int? {
return capitals[country].flatMap { capital in
return cities [capital]
}.flatMap { population in
return population * 1000
}
}
- 為什么使用可選值?
強(qiáng)?的類型系統(tǒng)能在代碼執(zhí)?前捕獲到錯(cuò)誤斑匪,?且顯式可選類型有助于避免由缺失值導(dǎo)致的意外崩潰呐籽。
//NSString *someString = ...;
//if ([ someString rangeOfString:@"swift"].location != NSNotFound) {
// NSLog(@"Someone mentioned swift!");
//}
//
//if let someString = ... {
//if someString.rangeOfString("swift").location != NSNotFound {
//print ("Found")
//}
//}
三、map 和 flatMap 的其他用法
// CollectionType : SequenceType
// public func map<T>(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
// SequenceType
// public func flatMap<S : SequenceType>(transform: (Self.Generator.Element) throws -> S) rethrows -> [S.Generator.Element]
// public func flatMap<T>(@noescape transform: (Self.Generator.Element) throws -> T?) rethrows -> [T]
let numbers = [1,2,3,4]
var result = numbers.map { $0 + 2 }
// [3,4,5,6]
result = numbers.flatMap { $0 + 2 }
// [3,4,5,6]
// s.flatMap(transform) == Array(s.map(transform).flatten())
let numbersCompound = [[1,2,3],[4,5,6]];
var res = numbersCompound.map { $0.map{ $0 + 2 } }
// [[3, 4, 5], [6, 7, 8]]
var flatRes = numbersCompound.flatMap { $0.map{ $0 + 2 } }
// [3, 4, 5, 6, 7, 8]
// s.flatMap(transform) == s.map(transform).filter{ $0 != nil }.map{ $0! }
let optionalArray: [String?] = ["AA", nil, "BB", "CC"];
var optionalResult: [String] = optionalArray.flatMap{ $0 }
// ["AA", "BB", "CC"]