sunhongyue4500
3/8/2017 - 3:39 AM

SwiftClosures.swift

//: Playground - noun: a place where people can play

import UIKit

var str = "Hello, playground"

let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]


// 1.撰写一个符合其类型要求的普通函数
func backward(_ s1: String, _ s2: String) -> Bool {
    return s1 > s2
}

// func sorted(by areInIncreasingOrder: (Element, Element) -> Bool) -> [Element]
var reversedNames = names.sorted(by: backward)

// 2
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
    return s1 > s2
})

// 3.写在一行上
reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in return s1 > s2 } )
print(reversedNames)

// 4.内部类型推断
reversedNames = names.sorted(by: { s1, s2 in return s1 > s2 } )
print(reversedNames)

// 5.单表达式闭包
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)

// 6.短参数命名
reversedNames = names.sorted(by: { $0 > $1 } )

// 7.操作符方法
reversedNames = names.sorted(by: >)


// 8.尾闭包
let digitNames = [
    0: "Zero", 1: "One", 2: "Two",   3: "Three", 4: "Four",
    5: "Five", 6: "Six", 7: "Seven", 8: "Eight", 9: "Nine"
]
let numbers = [16, 58, 510]

let strings = numbers.map {
    (number) -> String in
    var number = number
    var output = ""
    repeat {
        // 向前面加
        output = digitNames[number % 10]! + output
        print(output)
        number /= 10
    } while number > 0
    return output
}

print(strings)
// strings 常量被推断为字符串类型数组,即 [String]
// 其值为 ["OneSix", "FiveEight", "FiveOneZero"]

// 9.值捕获
func makeIncrementer(forIncrement amount: Int) -> (() -> Int) {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}

let incrementByTen = makeIncrementer(forIncrement: 10)
let incrementBySeven = makeIncrementer(forIncrement: 7)

incrementByTen()      // 两者没有关系
print(incrementBySeven())
print(incrementByTen()) // 40

// 10. 闭包是引用类型
let alsoIncrementByTen = incrementByTen
print(alsoIncrementByTen())

// 11.逃逸闭包: 闭包需要在函数返回之后被调用
//completionHandlers是类型() -> Void的一个数组
var completionHandlers: [() -> Void] = []
// 逃逸闭包
// 添加到外面的数组
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

// 非逃逸闭包
func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}

class SomeClass {
    var x = 10
    func doSomething() {
        // 必须使用self
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}

let instance = SomeClass()
instance.doSomething()
print(instance.x)
// 打印出 "200"

completionHandlers.first?()
print(instance.x)
// 打印出 "100"

// 12.自动闭包
// 自动闭包是一种自动创建的闭包,用于包装传递给函数作为参数的表达式。这种闭包不接受任何参数,当它被调用的时候,会返回被包装在其中的表达式的值。这种便利语法让你能够省略闭包的花括号,用一个普通的表达式来代替显式的闭包。
// 自动闭包让你能够延迟求值,因为直到你调用这个闭包,代码段才会被执行。延迟求值对于那些有副作用(Side Effect)和高计算成本的代码来说是很有益处的,因为它使得你能控制代码的执行时机
var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// 打印出 "5"
// customerProvider 的类型不是 String,而是 () -> String,
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// 打印出 "5"

print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// 打印出 "4"


// customersInLine is ["Alex", "Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: { customersInLine.remove(at: 0) } )
// 打印出 "Now serving Alex!"


// customersInLine is ["Ewa", "Barry", "Daniella"]
func serve(customer customerProvider: @autoclosure () -> String) {
    print("Now serving \(customerProvider())!")
}
serve(customer: customersInLine.remove(at: 0))
// 打印 "Now serving Ewa!"

// 逃逸+自动闭包
// customersInLine i= ["Barry", "Daniella"]
var customerProviders: [() -> String] = []
func collectCustomerProviders(_ customerProvider: @autoclosure @escaping () -> String) {
    customerProviders.append(customerProvider)
}
collectCustomerProviders(customersInLine.remove(at: 0))
collectCustomerProviders(customersInLine.remove(at: 0))

print("Collected \(customerProviders.count) closures.")
// 打印 "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// 打印 "Now serving Barry!"
// 打印 "Now serving Daniella!"