一、 基本概念
- 变量,类型,初始化
var str: String
str = "Hello World"
str.uppercaseString
var str2: String = "Hello World2"
- 类型推断,强类型
var str3 = "Hello World3"
- 可选类型,枚举
//Optional
var errorCodeString: String?
errorCodeString = "404"
errorCodeString = nil
- 强制解包发现为nil导致运行时崩溃,不安全!
let theError: String = errorCodeString!
- if 语句
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)")
}
}
}
- 简化,都不为nil时执行。where相当于if判断语句
if let theError = errorCodeString, errorCodeInteger = Int(theError) where errorCodeInteger == 404 {
print("\(theError): \(errorCodeInteger)")
}
4 .隐式解包的可选 -- 不安全!
var errorCodeString2: String!
errorCodeString2 = "404"
errorCodeString2 = nil
- 如果为nil,导致运行时崩溃,不安全!
let theError2: String = errorCodeString2
- 万能的 if, 可选绑定
if errorCodeString2 != nil {
let theError2: String = errorCodeString2
}
if let theError2 = errorCodeString2 {
print(theError2)
}
注意:
如果一个变量之后可能变成nil的话请不要使用隐式解包的可选类型。
如果你需要在变量的生命周期中判断是否是nil的话,请使用普通可选类型。
二、安全地使用可选值
- Swift 的可选类型可以⽤来表⽰可能缺失或是计算失败的值。
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")
}
- 可选绑定,可以让你避免写 ! 后缀。不再需要显式地使⽤强制解包。
if let madridPopulation = cities["Madrid"] {
print ("The population of Madrid is \(madridPopulation * 1000)")
} else {
print ("Unknown city: Madrid")
}
- 空合运算符
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 类型标签来避开创建显式闭包 myOptional ?? myDefaultValue -> myOptional ?? { myDefaultValue }
- 可选链
可选链式调用(Optional Chaining)是一种可以在当前值可能为nil的可选值上请求和调用属性、方法及下标的方法。如果可选值有值,那么调用就会成功;如果可选值是nil,那么调用将返回nil。多个调用可以连接在一起形成一个调用链,如果其中任何一个节点为nil,整个调用链都会失败,即返回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 {
}
}
}
- 使⽤问号运算符来尝试对可选类型进⾏解包。当任意⼀个组成项失败时,整条语句链将返回 nil。
if let myState = order.person?.address?.state {
print ("This order will be shipped to \(myState)")
} else {
print ("Unknown person, address, or state.")
}
- 分支上的可选值
- switch 语句
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 语句: 在当⼀些条件不满⾜时,可以尽早退出当前作⽤域,避免不必要的计算。可以使⽤⾮可选的 population 值,⽐嵌套 if let 语句时更简单。
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
}
}
- 可选映射 : 若可选值存在,你可能会想操作它,否则返回 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
}
}
- 为什么使用可选值?
强⼤的类型系统能在代码执⾏前捕获到错误,⽽且显式可选类型有助于避免由缺失值导致的意外崩溃。
//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(@noescape transform: (Self.Generator.Element) throws -> T) rethrows -> [T]
// SequenceType
// public func flatMap(transform: (Self.Generator.Element) throws -> S) rethrows -> [S.Generator.Element]
// public func flatMap(@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"]