Swift4 闭包,例子代码

闭包

苹果官方文档 闭包

苹果官方文档翻译 闭包

  • 闭包表达式

      { (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!"
    
posted @ 2018-04-01 18:16  youv  阅读(202)  评论(2编辑  收藏  举报