当前位置: 首页 > 编程学习 > 其它语言 > Swift > 正文

Swift4 闭包,例子代码

2018-04-22 来源:博客园/CC_Joy

闭包

苹果官方文档 闭包

苹果官方文档翻译 闭包

闭包表达式

  { (parameters) -> (return type) in
    statements
  }     
Sorted 方法

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"]
闭包表达版本
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 } )
简写实际参数名
reversedNames = names.sorted(by: { $0 > $1 } )
运算符函数
reversedNames = names.sorted(by: >)

尾随闭包

func someFunctionThatTakesAClosure(closure:() -> Void){
   //function body goes here
}
 
//here's how you call this function without using a trailing closure
 
someFunctionThatTakesAClosure({
   //closure's body goes here
})
 
//here's how you call this function with a trailing closure instead
 
someFunctionThatTakesAClosure() {
   // trailing closure's body goes here
}

如果闭包为函数唯一实参,并作为尾随闭包,可以省略括号

reversedNames = names.sorted { $0 > $1 }
let digitNames = [
0: "Zero",1: "One",2: "Two",  3: "Three",4: "Four",
5: "Five",6: "Six",7: "Seven",8: "Eight",9: "Nine"
]
 
let strings = numbers.map {
    (number) -> String in
    var number = number
    var output = ""
    repeat {
        output = digitNames[number % 10]! + output
        number /= 10
    } while number > 0
    return output
}
// strings is inferred to be of type [String]
// its value is ["OneSix", "FiveEight", "FiveOneZero"]

捕获值

func makeIncrementer(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementer() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementer
}
 
let incrementByTen = makeIncrementer(forIncrement: 10)
 
incrementByTen()
  //return a value of 10
  incrementByTen()
  //return a value of 20
  incrementByTen()
  //return a value of 30
 
let incrementBySeven = makeIncrementer(forIncrement: 7)
incrementBySeven()
// returns a value of 7
 
incrementByTen()
// returns a value of 40

闭包是引用类型

let alsoIncrementByTen = incrementByTen
  alsoIncrementByTen()
  //return a value of 50

闭包逃逸

闭包作为一个实际参数传递给一个函数的时候,我们就说这个闭包逃逸了。
声明一个接受闭包作为形式参数的函数时,你可以在形式参数前写 @escaping 来明确闭包是允许逃逸的。

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

闭包 @escaping 意味着你必须在闭包中显式地引用 self

func someFunctionWithNonescapingClosure(closure: () -> Void) {
    closure()
}
 
class SomeClass {
    var x = 10
    func doSomething() {
        someFunctionWithEscapingClosure { self.x = 100 }
        someFunctionWithNonescapingClosure { x = 200 }
    }
}
 
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
 
completionHandlers.first?()
print(instance.x)
// Prints "100"

自动闭包

自动闭包是一种自动创建的用来把作为实际参数传递给函数的表达式打包的闭包。

自动闭包允许你延迟处理,因此闭包内部的代码直到你调用它的时候才会运行。

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"
 
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"
 
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

如果闭包永远不被调用,那么闭包里边的表达式就永远不会求值。

var customersInLine = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
print(customersInLine.count)
// Prints "5"
 
let customerProvider = { customersInLine.remove(at: 0) }
print(customersInLine.count)
// Prints "5"
 
print("Now serving \(customerProvider())!")
// Prints "Now serving Chris!"
print(customersInLine.count)
// Prints "4"

@autoclosure 标志标记它的形式参数使用了自动闭包。调用函数就像它接收了一个 String 实际参数而不是闭包,实际参数自动地转换为闭包。

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

自动闭包允许逃逸,就同时使用 @autoclosure 和 @escaping 标志。

// customersInLine is ["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.")
// Prints "Collected 2 closures."
for customerProvider in customerProviders {
    print("Now serving \(customerProvider())!")
}
// Prints "Now serving Barry!"
// Prints "Now serving Daniella!"