Swift3-文檔學習記錄

重新再學一遍Swift,現在是3.1版本.
默默的吐槽一下,Swift更新好快,下半年還要出Swift4,不過還是得跟上步伐,哈哈


常量和變量

let number: Int = 10
var numberstring: String = "hello world"

整數

let  value1 = Int8.min
let value2 = UInt32.max
//分為有符號整數,無符號整數類型

浮點數

let value3: Float = 5.20
let value4:Double = 3.141592654
//Double代表 64 位的浮點數。15位精確度
//Float 代表 32 位的浮點數。6位精確度

數值型字面量

let decimalInteger = 17
//一個十進制數,沒有前綴

let binaryInteger = 0b10001
//一個二進制數,前綴是 0b

let octalInteger = 0o21 
//一個八進制數,前綴是 0o

let hexadecimalInteger = 0x11
//一個十六進制數,前綴是 0x

let decimalDouble = 12.1875
let exponentDouble = 1.21875e1
let hexadecimalDouble = 0xC.3p0
//十進制的浮點字面量還有一個可選的指數,用大寫或小寫的 e 表示
//十六進制的浮點字面量必須有指數,用大寫或小寫的 p 來表示

整數類型轉換

let one:Int16 = 22
let two:Int32 = 77
let sum1 = two + Int32(one)
//SomeType(ofInitialValue)  是調用 Swift 類型初始化器并傳入一個初始值的默認方法

let three:Int8 =  33
let four:Double = 33.33
let sum2 = Double(three) + four
//浮點轉換為整數必須顯式地指定類型
//浮點轉換為整數也必須顯式地指定類型

類型別名

typealias Integer16 = Int16
//類型別名可以為已經存在的類型定義了一個新的可選名字
//用 typealias 關鍵字定義類型別名

布爾值

let success = true
let fail = false

元組

let http404 = (statusCode: 404: Int, description: "Not Found": String)
//元組把多個值合并成單一的復合型的值。元組內的值可以是任何類型,而且可以不必是同一類型

可選項

//可選項說明這里要么有一個值,要么值缺失
//例如在類型轉換的時候,類型可能轉換失敗,初始化器可能會構造失敗,變量或者常量將類型聲明成可選型,就可以處理失敗的情況了
let possibleNumber = "123"
let convertedNumber = Int(possibleNumber)

//nil
//nil是可選項值缺失的一種特殊類型,任何類型的可選項都可以設置成nil
//nil 不能用于非可選的常量或者變量

//可選項的強制展開
//可以利用 if 語句通過比較 nil 來判斷一個可選中是否包含值
if let converedNumber != nil {
  print("convertedNumber has an integer value of \(convertedNumber!).")

//可選項綁定
//使用可選項綁定來判斷可選項是否包含值,如果包含就把值賦給一個臨時的常量或者變量
//使用 if  進行可選項綁定格式:
if let constantName = someOptional { 
    statements 
} 

if let tempValue = Int(possiableNumber) {
  print("\'\(possibleNumber)\' has an integer value of \(actualNumber)")
} else {
    print("\'\(possibleNumber)\' could not be converted to an integer")
}

//隱式展開可選項
在聲明的類型后邊添加一個嘆號( String! )而非問號(  String? ) 來書寫隱式展開可選項

錯誤處理

//在函數聲明過程當中加入 throws 關鍵字來表明這個函數會拋出一個錯誤
//當你調用了一個可以拋出錯誤的函數時,需要在表達式前預置 try 關鍵字
//Swift 會自動將錯誤傳遞到它們的生效范圍之外,直到它們被 catch 分句處理
//do 語句創建了一個新的容器范圍,可以讓錯誤被傳遞到到不止一個的 catch 分句里
func makeASandwich() throws {
    
}
 
do {
    try makeASandwich()
    eatASandwich()
} catch Error.OutOfCleanDishes {
    washDishes()
} catch Error.MissingIngredients(let ingredients) {
    buyGroceries(ingredients)
}

斷言

//在任何判斷條件可能為假但是一定要絕對地為真才能讓代碼繼續執行的時候才使用斷言,進行調試

//斷言可以“斷言”一個條件是否為真。你可以使用斷言確保在運行其他代碼之前必要的條件已經被滿足。
//如果條件判斷為 true,代碼運行會繼續進行;如果條件判斷為 false,代碼運行結束,你的應用也就中止
//斷言允許附加一條調試的信息

//如何使用斷言:
//使用全局函數 assert(_:_:)  函數來寫斷言。
//向 assert(_:_:) 函數傳入一個結果為 true 或者 false 的表達式以及一條會在結果為 false 的時候顯式的信息
let age = 16
assert(age > 18, "用戶屬于未成年人")

基本運算符

1. 賦值運算符( a = b )

2. 算數運算符 
  - 加 ( + )
  - 減 ( - )
  - 乘 ( * )
  - 除 ( / )
Swift 算術運算符默認不允許值溢出,可以使用 Swift 的溢出操作符(比如  a &+ b  )來行使溢出行為

3. 余數運算符
余數運算符( a % b )可以求出多少個 b  的倍數能夠剛好放進 a  中并且返回剩下的值(就是我們所謂的余數)

4. 一元減號運算符( - ),一元加號運算符 ( + )

5. 組合賦值符號 
+=  -=  /=  *=  %=

6. 比較運算符
相等 ( a == b )
不相等 ( a != b )
大于 ( a > b )
小于 ( a < b )
大于等于 ( a >= b )
小于等于 ( a <= b )
等價運算符( ===  和 !== ),可以使用它們來判斷兩個對象的引用是否相同

7.  三元條件運算符
(  a ? b : c )

8. 合并空值運算符 
( a ?? b )如果可選項 a  有值則展開,如果沒有值,是 nil  ,則返回默認值 b 。表達式 a 必須是一個可選類型。表達式 b  必須與 a  的儲存類型相同
 短路計算:  如果 a  的值是非空的, b  的值將不會被考慮

9. 區間運算符
閉區間運算符: ( a...b )
半開區間運算符: ( a..<b )

10.  邏輯運算符
邏輯 非  ( !a ): 把 true  變成 false  , 把 false  變成 true
邏輯 與  ( a && b ): 邏輯表達式的兩個值都為 true  ,整個表達式的值才為 true
邏輯 或  ( a || b ): 兩個值之間只要有一個為 true  那么整個表達式就是 true

控制流語句

//for 循環
for index in 1...9{
    print("\(index) times 9 is \(index * 9)")
}
//stride(from:to:by:) 函數來跳過不想要的標記

//while循環
//while 循環通過判斷單一的條件開始。如果條件為 true ,語句的合集就會重復執行直到條件變為 false
while condition {
    statements
}

 //repeat-while 循環,在判斷循環條件之前會執行一次循環代碼塊。然后會繼續重復循環直到條件為 false 
repeat {
    statements
} while condition

// if  else 條件語句

//switch 匹配語句
switch some value to consider {
case value 1:
    respond to value 1
case value 2,
value 3:
    respond to value 2 or 3
default:
    otherwise, do something else
}
//Swift 里的 switch 語句不會默認從每個情況的末尾貫穿到下一個情況里
//每一個情況的函數體必須包含至少一個可執行的語句
//一個 switch 情況中匹配多個值可以用逗號分隔,并且可以寫成多行
//可以使用元組來在一個 switch 語句中測試多個值,使用下劃線( _)來表明匹配所有可能的值
//switch 情況可以將匹配到的值臨時綁定為一個常量或者變量
//switch 情況可以使用 where 分句來檢查額外的情況

轉移控制語句

//continue:   continue 語句告訴循環停止正在做的事情并且再次從頭開始循環的下一次遍歷。它是說“我不再繼續當前的循環遍歷了”而不是離開整個的循環

//break:   break 語句會立即結束整個控制流語句。當你想要提前結束 switch 或者循環語句或者其他情況時可以在 switch 語句或者循環語句中使用 break 語句

//fall through:  從每個情況的末尾貫穿到下一個情況中

//標簽語句: 在循環前加上開始標簽,在控制語句前加上結束標簽
label name: while condition {
    statements
}

//提前退出: 使用 guard: 一個條件必須是真才能執行 guard 之后的語句
//guard 語句總是有一個 else 分句—— else 分句里的代碼會在條件不為真的時候執行
//如果 guard 語句的條件被滿足,代碼會繼續執行直到 guard 語句后的花括號

func greet(person: [String: String]) {
    guard let name = person["name"] else {
        return
    }
    
    print("Hello \(name)!")
    
    guard let location = person["location"] else {
        print("I hope the weather is nice near you.")
        return
    }
    
    print("I hope the weather is nice in \(location).")
}
greet(["name": "John"])
// prints "Hello John!"
// prints "I hope the weather is nice near you."
greet(["name": "Jane", "location": "Cupertino"])
// prints "Hello Jane!"
// prints "I hope the weather is nice in Cupertino."

字符串和字符

//字符串字面量
let someString = "Some string literal value"

//空字符串的初始化
var emptyString = ""             
var anotherEmptyString = String()

//string是值類型,傳遞的是拷貝值

// 操作字符
//通過在 for-in循環里遍歷 characters屬性訪問 String 中的每一個獨立的 Character值

//字符串插值
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier) * 2.5)"

//字符串字面量中的特殊字符
//轉義特殊字符 \0 (空字符), \\ (反斜杠), \t (水平制表符), \n (換行符), \r(回車符), \" (雙引號) 以及 \' (單引號)
//任意的 Unicode 標量,寫作 \u{n},里邊的 n是一個 1-8 個與合法 Unicode 碼位相等的16進制數字

//字符統計 使用 characters.count 
//字符范圍: 使用characters.indices

//訪問和修改字符串:
Index startndex  endIndex  index(before:)   index(after: )  index(_:offsetBy:) 

//刪除和插入:
//要給字符串的特定索引位置插入字符,使用 insert(_:at:)方法,另外要沖入另一個字符串的內容到特定的索引,使用 insert(contentsOf:at:) 方法
//要從字符串的特定索引位置移除字符,使用 remove(at:)方法,另外要移除一小段特定范圍的字符串,使用 removeSubrange(_:) 方法:

//字符串比較
//字符串和字符相等性 ==   !=
//前綴和后綴相等性 
//要檢查一個字符串是否擁有特定的字符串前綴或者后綴,調用字符串的 hasPrefix(_:)和 hasSuffix(_:)方法,它們兩個都會接受一個 String 類型的實際參數并且返回一個布爾量值

數組Array

//創建數組
let array1 = [Int]() //空數組
let array2  = [Array](repeating: 3,count: 3)
//傳給初始化器對應類型的默認值(叫做 repeating)和新數組元素的數量(叫做 count):

//訪問和修改數組
//count isEmpty append(_: )  insert(_:at:) remove( at: )   removeLast() 
//遍歷數組
enumerated()方法返回數組中每一個元素的元組,包含了這個元素的索引和值
for (index, value) in shoppingList.enumerated() {
    print("Item \(index + 1): \(value)")
}
// Item 1: Six eggs
// Item 2: Milk
// Item 3: Flour
// Item 4: Baking Powder
// Item 5: Bananas

合集Set

//合集將同一類型且不重復的值無序地儲存在一個集合當中。當元素的順序不那么重要的時候你就可以使用合集來代替數組,或者你需要確保元素不會重復的時候
 //創建合集
var letters = Set<Character>()
print("letters is of type Set<Character> with \(letters.count) items.")
//使用數組字面量創建合集
var favoriteGenres: Set<String> = ["Rock", "Classical", "Hip hop"]

//訪問和修改合集
count isEmpty insert(_: )  remove(_: )  removeAll()  contains(_:)  

//遍歷合集
//Swift 的 Set類型是無序的。要以特定的順序遍歷合集的值,使用 sorted()方法,它把合集的元素作為使用 < 運算符排序了的數組返回
for genre in favoriteGenres.sorted() {
    print("\(genre)")
}

//合集操作
//使用 intersection(_:)方法來創建一個只包含兩個合集共有值的新合集;
//使用 symmetricDifference(_:)方法來創建一個只包含兩個合集各自有的非共有值的新合集;
//使用 union(_:)方法來創建一個包含兩個合集所有值的新合集;
//使用 subtracting(_:)方法來創建一個兩個合集當中不包含某個合集值的新合集。

let oddDigits: Set = [1, 3, 5, 7, 9]
let evenDigits: Set = [0, 2, 4, 6, 8]
let singleDigitPrimeNumbers: Set = [2, 3, 5, 7]
 
oddDigits.union(evenDigits).sorted()
// [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
oddDigits.intersection(evenDigits).sorted()
// []
oddDigits.subtracting(singleDigitPrimeNumbers).sorted()
// [1, 9]
oddDigits.symmetricDifference(singleDigitPrimeNumbers).sorted()
// [1, 2, 9]

//合集成員關系和相等性

//使用“相等”運算符 ( == )來判斷兩個合集是否包含有相同的值;
//使用 isSubset(of:) 方法來確定一個合集的所有值是被某合集包含;
//使用 isSuperset(of:)方法來確定一個合集是否包含某個合集的所有值;
//使用 isStrictSubset(of:) 或者 isStrictSuperset(of:)方法來確定是個合集是否為某一個合集的子集或者超集,但并不相等;
//使用 isDisjoint(with:)方法來判斷兩個合集是否擁有完全不同的值。

let houseAnimals: Set = ["", ""]
let farmAnimals: Set = ["", "", "", "", ""]
let cityAnimals: Set = ["", ""]
 
houseAnimals.isSubset(of: farmAnimals)
// true
farmAnimals.isSuperset(of: houseAnimals)
// true
farmAnimals.isDisjoint(with: cityAnimals)
// true

字典Dictionary

//創建字典
//Dictionary<Key, Value>,其中的 Key是用來作為字典鍵的值類型, Value就是字典為這些鍵儲存的值的類型。
//簡寫: [key: value]
var namesOfIntegers = [Int: String]() //空字典
//用字典字面量創建字典
var airports: [String: String] = ["YYZ": "Toronto Pearson", "DUB": "Dublin"]

//訪問和修改字典

//count  isEmpty   removeValue(forKey:)
//使用字典的 updateValue(_:forKey:)方法來設置或者更新特點鍵的值
//updateValue(_:forKey:)方法返回一個字典值類型的可選項值
//使用下標腳本語法給一個鍵賦值 nil來從字典當中移除一個鍵值對:

//遍歷字典
for (airportCode, airportName) in airports {
    print("\(airportCode): \(airportName)")
}
//通過訪問字典的 keys和 values屬性來取回可遍歷的字典的鍵或值的集合
for airportCode in airports.keys {
    print("Airport code: \(airportCode)")
}
// Airport code: YYZ
// Airport code: LHR
 
for airportName in airports.values {
    print("Airport name: \(airportName)")
}

函數 Func

//1. 定義和調用函數
func greetAgain(person: String) -> String {
    return "Hello again, " + person + "!"
}
print(greetAgain(person: "Anna"))

//2. 函數的形式參數和返回值
無形式參數的函數
func sayHelloWorld() -> String {
    return "hello, world"
}
print(sayHelloWorld())

多形式參數的函數
func greet(person: String, alreadyGreeted: Bool) -> String {
    if alreadyGreeted {
        return greetAgain(person: person)
    } else {
        return greet(person: person)
    }
}
print(greet(person: "Tim", alreadyGreeted: true))
// Prints "Hello again, Tim!"

無返回值的函數
func printAndCount(string: String) -> Int {
    print(string)
    return string.characters.count
}
func printWithoutCounting(string: String) {
    let _ = printAndCount(string: string)
}
printAndCount(string: "hello, world")
// prints "hello, world" and returns a value of 12
printWithoutCounting(string: "hello, world")
// prints "hello, world" but does not return a value

多返回值的函數
func minMax(array: [Int]) -> (min: Int, max: Int) {
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

可選元組返回類型
func minMax(array: [Int]) -> (min: Int, max: Int)? {
    if array.isEmpty { return nil }
    var currentMin = array[0]
    var currentMax = array[0]
    for value in array[1..<array.count] {
        if value < currentMin {
            currentMin = value
        } else if value > currentMax {
            currentMax = value
        }
    }
    return (currentMin, currentMax)
}

if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
    print("min is \(bounds.min) and max is \(bounds.max)")
}

3. 函數實際參數標簽和形式參數名
可以指定實際參數標簽
可以使用默認的參數標簽(即是形式參數名)
可以使用_下劃線忽略標簽
可以給形式參數賦一個默認值,在調用函數時可以省略參數名
使用...表示可變形式參數,可以傳入多個參數

輸入輸出形式參數
在形式參數定義開始的時候在前邊添加一個 inout關鍵字可以定義一個輸入輸出形式參數。
輸入輸出形式參數有一個能輸入給函數的值,函數能對其進行修改,還能輸出到函數外邊替換原來的值。
調用函數時,在參數前面加上&,表明可以被函數修改
func swapTwoInts(_ a: inout Int, _ b: inout Int) {
    let temporaryA = a
    a = b
    b = temporaryA
}
var someInt = 3
var anotherInt = 107
swapTwoInts(&someInt, &anotherInt)
print("someInt is now \(someInt), and anotherInt is now \(anotherInt)")
// prints "someInt is now 107, and anotherInt is now 3"

函數類型
每一個函數都有一個特定的函數類型,它由形式參數類型,返回類型組成。
可以用作函數類型參數,和返回函數類型

內嵌函數
函數可以內可以嵌套函數(局部函數)

屬性Property

1. 存儲屬性
存儲屬性是一個作為特定類和結構體實例一部分的常量或變量
延遲存儲屬性的初始值在其第一次使用時才進行計算(lazy 標注)
2. 計算屬性
類、結構體和枚舉也能夠定義計算屬性,提供一個讀取器和一個可選的設置器來間接得到和設置其他的屬性和值
//如果一個計算屬性的設置器沒有為將要被設置的值定義一個名字,那么他將被默認命名為 newValue
struct AlternativeRect {
    var origin = Point()
    var size = Size()
    var center: Point {
        get {
            let centerX = origin.x + (size.width / 2)
            let centerY = origin.y + (size.height / 2)
            return Point(x: centerX, y: centerY)
        }
        set {
            origin.x = newValue.x - (size.width / 2)
            origin.y = newValue.y - (size.height / 2)
        }
    }
}
3. 屬性觀察者
屬性觀察者會觀察并對屬性值的變化做出回應。每當一個屬性的值被設置時,屬性觀察者都會被調用,即使這個值與該屬性當前的值相同。
willSet 會在該值被存儲之前被調用。
didSet 會在一個新值被存儲后被調用。
4. 全局和局部變量
計算屬性和觀察屬性的能力同樣對全局變量和局部變量有效
全局變量是定義在任何函數、方法、閉包或者類型環境之外的變量。
局部變量是定義在函數、方法或者閉包環境之中的變量
5. 類型屬性
實例屬性是屬于特定類型實例的屬性。每次你創建這個類型的新實例,它就擁有一堆屬性值,與其他實例不同。
可以定義屬于類型本身的屬性,不是這個類型的某一個實例的屬性。這個屬性只有一個拷貝,無論你創建了多少個類對應的實例。這樣的屬性叫做類型屬性
使用 static 關鍵字來開一類型屬性。對于類類型的計算類型屬性,你可以使用 class 關鍵字來允許子類重寫父類的實現
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}
查詢和設置類型屬性
類型屬性使用點語法來查詢和設置,與類型屬性一致。總之,類型屬性在類里查詢和設置,而不是這個類型的實例
print(SomeStructure.storedTypeProperty)
// prints "Some value."
SomeStructure.storedTypeProperty = "Another value."
print(SomeStructure.storedTypeProperty)
// prints "Another value."
print(SomeEnumeration.computedTypeProperty)
// prints "6"
print(SomeClass.computedTypeProperty)
// prints "27"

方法Method

1. 實例方法
方法 是關聯了特定類型的函數
實例方法 是屬于特定類實例、結構體實例或者枚舉實例的函數
實例方法默認可以訪問同類下所有其他實例方法和屬性。實例方法只能在類型的具體實例里被調用
使用 self屬性來在當前實例當中調用它自身的方法
 
在實例方法中修改值類型
結構體和枚舉是值類型。默認情況下,值類型屬性不能被自身的實例方法修改。
需要在特定的方法中修改結構體或者枚舉的屬性,你可以選擇將這個方法異變
使用mutating 關鍵字
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveByX(deltaX: Double, y deltaY: Double) {
        x += deltaX
        y += deltaY
    }
}
var somePoint = Point(x: 1.0, y: 1.0)
somePoint.moveBy(x: 2.0, y: 3.0)
print("The point is now at (\(somePoint.x), \(somePoint.y))")
// prints "The point is now at (3.0, 4.0)"

在異變方法里指定自身
異變方法可以指定整個實例給隱含的 self屬性。
struct Point {
    var x = 0.0, y = 0.0
    mutating func moveBy(x deltaX: Double, y deltaY: Double) {
        self = Point(x: x + deltaX, y: y + deltaY)
    }
}
2. 類型方法
定義在類型本身調用的方法。這類方法被稱作類型方法。
你可以通過在 func關鍵字之前使用 static關鍵字來明確一個類型方法。
類同樣可以使用 class關鍵字來允許子類重寫父類對類型方法的實現。


閉包


### 什么是閉包
閉包是代碼中引用和傳遞的功能性的獨立模塊

### 閉包形式:

全局函數是一個有名字但不會捕獲任何值的閉包;
內嵌函數是一個有名字且能從其上層函數捕獲值的閉包;
閉包表達式是一個輕量級語法所寫的可以捕獲其上下文中常量或變量值的沒有名字的閉包。

### 閉包的優化:

-  利用上下文推斷形式參數和返回值的類型;
- 單表達式的閉包可以隱式返回;
- 簡寫實際參數名;
- 尾隨閉包語法

### 閉包表達式語法:

在很簡短的一行里面寫完的一種語法
  { (parameters) -> (return type) in
      statements
    }

閉包的函數整體部分由關鍵字 in 導入,這個關鍵字表示閉包的形式參數類型和返回類型定義已經完成,并且閉包的函數體即將開始

sorted(by:)://會根據你提供的排序閉包將已知類型的數組的值進行排序,返回新數組
  let names = ["Chris","Alex","Ewa","Barry","Daniella"]
  func backward(_ s1: String, _ s2: String) -> Bool {
      return s1 > s2
  }
  var reversedNames = names.sorted(by: backward)
  // reversedNames is equal to ["Ewa", "Daniella", "Chris", "Barry", "Alex"]

  提供排序閉包的一個方法是寫一個符合其類型需求的普通函數,并將它作為 sorted(by:) 方法的形式參數傳入
 ` reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )`

-   從語境中推斷類型:
 ` reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )`

- 從單表達式閉包隱式返回:
  `reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )`


-   簡寫的實際參數名:Swift 自動對行內閉包提供簡寫實際參數名,你也可以通過 $0 , $1 , $2 等名字來引用閉包的實際參數值
 ` reversedNames = names.sorted(by: { $0 > $1 } )`


- 運算符函數簡寫:Swift 的 String 類型定義了關于大于號( >)的特定字符串實現,讓其作為一個有兩個 String 類型形式參數的函數并返回一個 Bool 類型的值
  `reversedNames = names.sorted(by: >)`

###  尾隨閉包:
當需要將一個很長的閉包表達式作為函數最后一個實際參數傳遞給函數,使用尾隨閉包將增強函數的可讀性。尾隨閉包是一個被書寫在函數形式參數的括號外面(后面)的閉包表達式:
`  reversedNames = names.sorted() { $0 > $1 }`

  如果閉包表達式作為函數的唯一實際參數傳入,而你又使用了尾隨閉包的語法,那你就不需要在函數名后邊寫圓括號了:
 ` reversedNames = names.sorted { $0 > $1 }`

### 捕獲值:
一個閉包能夠從上下文捕獲已被定義的常量和變量。即使定義這些常量和變量的原作用域已經不存在,閉包仍能夠在其函數體內引用和修改這些值


### 引用類型閉包:
無論你什么時候安賦值一個函數或者閉包給常量或者變量,你實際上都是將常量和變量設置為對函數和閉包的引用


### 逃逸閉包:
 當閉包作為一個實際參數傳遞給一個函數的時候,我們就說這個閉包逃逸了,因為它可以在函數返回之后被調用。

**使用關鍵字: \@escaping 明確閉包是逃逸的,使用時,必須顯式的引用self**

閉包可以逃逸的一種方法是被儲存在定義于函數外的變量里,例如: 多函數接收閉包實際參數來作為啟動異步任務的回調。函數在啟動任務后返回,但是閉包要直到任務完成——閉包需要逃逸,以便于稍后調用

### 自動閉包: 
自動閉包是一種自動創建的用來把作為實際參數傳遞給函數的表達式打包的閉包。它不接受任何實際參數,并且當它被調用時,它會返回內部打包的表達式的值。這個語法的好處在于通過寫普通表達式代替顯式閉包而使你省略包圍函數形式參數的括號

自動閉包允許你延遲處理,因此閉包內部的代碼直到你調用它的時候才會運行
**使用關鍵字: \@autoclosure 標志標記它的形式參數使用了自動閉包**

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容