美文网首页
7.闭包 Closures Swift官方文档——版纳的笔记

7.闭包 Closures Swift官方文档——版纳的笔记

作者: KevinFromChina | 来源:发表于2018-03-28 20:21 被阅读0次
    //: Playground - noun: a place where people can play
    
    import UIKit
    
    // # define:闭包是自身闭合并能包裹上下文常变量的代码块
    
    // # 闭包表达式
    // 函数是特殊形式的闭包,也能捕获值
    // trick: sorted(by:)方法:根据提供的排序闭包将已知类型的数组的值进行排序,结果是排列后前后任何两个元素都满足传入该方法的结果为true
    let names = ["Chris","Alex","Ewa","Barry","Daniella"]
    // 用函数方法
    func backward(_ s1: String, _ s2: String) -> Bool {
        return s1 > s2
    }
    var reversedNames = names.sorted(by: backward) // 函数亦闭包
    // 用闭包表达式.闭包能够使用常量形式参数、变量形式参数和输入输出形式参数,但不能提供默认值。可变形式参数也能使用,但需要在形式参数列表的最后面使用。元组被用来作为形式参数和返回类型。
    let anotherBackward = { (s1: String, s2: String) -> Bool in return s1 > s2 }
    reversedNames = names.sorted(by: anotherBackward)
    // 可以从语境中推断类型,此时只保留必要内容就可以了.
    let anotherBackward2: (String, String) -> Bool = { s1, s2 in return s1 > s2 }
    let also: (String, String) -> Void = { _, _ in 1 } // 如果参数没有被用到
    let some = {}
    
    // 从单表达式(如只有return s1 > s2)闭包隐式返回
    let anotherBackward3: (String, String) -> Bool = { s1, s2 in s1 > s2 }
    let anotherBackward4: (String, String) -> Bool = { $0 > $1 }
    var reversedNamesAgain = names.sorted(by: { $0 > $1 }) // 从函数调用时也能推断闭包类型并且允许省略一些内容
    anotherBackward4("S", "H") // 调用闭包的方法,和无实际参数标签的函数调用一样
    // 简单地传递一个大于号, Swift 将推断你想使用大于号特殊字符串函数实现:
    reversedNames = names.sorted(by: >)
    
    // # 尾随闭包
    // 闭包比较长不能写成一行时,写在圆括弧内又在花括弧内实在很不舒服,所以有了尾随闭包
    // 作为最后一个实际参数可用尾随闭包,提高代码可读性
    // trick:尾随闭包不写闭包的实际参数标签(比如closure:)
    reversedNames = names.sorted() { $0 > $1 } // 使用尾随闭包
    reversedNames = names.sorted { $0 > $1 } // 作为唯一的参数并且使用了尾随闭包,就不必在函数名后写圆括号了
    // trick: 整型数组的map映射函数
    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, 567, 234235]
    let strings = numbers.map {
        (number: Int) -> String in
        var number = number // 这样的赋值在函数或闭包中都是可以的,因为实际上闭包是从in后开始而函数是从花括号开始的,内部定义的量与外部同名了都会暂时覆盖之.即Swift允许一次重新命名的机会,但是最好不要这样做.如func someFunc(a: Int) { var a = a; a += 1 }
        var output = ""
        repeat {
            output = digitNames[number % 10]! + output
            number /= 10
        } while number > 0
        return output
    }
    
    // # 捕获值
    // 强大的捕获,内嵌函数
    func makeIncrementer(forIncrement amount: Int) -> () -> Int {
        var runningTotal = 0
        func incrementer() -> Int {
            runningTotal += amount
            return runningTotal
        }
        return incrementer
    }
    let incrementByTen = makeIncrementer(forIncrement: 10)
    // runningTotal和amount看起来好像早就不见了,而实际上整个makeIncrementer代码块因部分被引用而存在
    incrementByTen()
    incrementByTen()
    incrementByTen()
    
    // # 闭包是引用类型***
    // 所有的类型,任何一个实例名字都是对某块内存空间的引用.值类型和引用类型的区别是传递这个名字时,是传递了实例拷贝还是名字的拷贝
    let alsoIncrementByTen = incrementByTen
    alsoIncrementByTen()
    
    // # 逃逸闭包
    // 闭包作为实际参数传入,在函数中被赋给外部常变量以便函数结束后闭包还能再使用称为逃逸.在形式参数类型前加上@escaping表明其可以逃逸
    var completionHandlers: [() -> Void] = []
    func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
        completionHandlers.append(completionHandler)
    }
    
    func someFunctionWithNonescapingClosure(closure: () -> Void) {
        closure()
    }
    class SomeClass {
        var x = 10
        func doSomething() {
            someFunctionWithEscapingClosure { self.x = 100 } // 作为逃逸闭包被外部引用,加上self关键字
            someFunctionWithNonescapingClosure { x = 200 }
        }
    }
    let instance = SomeClass()
    instance.doSomething()
    print(instance.x)
    completionHandlers[0]()
    print(instance.x)
    
    // # 自动闭包
    // 有名字的闭包,所以不能接收参数,但是可以返回值
    // 定义时不调用,所以延迟求值
    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"
    // trick:标记@autoclosure可以将表达式自动转为闭包
    
    // trick:立即执行的闭包,结尾加上(),可以立即获得闭包的返回值***
    var a = { () -> Int in
        let b = Array(repeating: "S", count: 8)
        return b.count
    }()
    // 单返回值无参数闭包可以省略in等前表达式
    a = {
        let b = Array(repeating: "S", count: 8)
        return b.count
    }()
    
    // trick:实现闭包***
    func compareBy(a: Int, b: Int, _ closure: (Int, Int) -> String) -> String {
        return closure(a, b)
    }
    var immediateResult = {
        (a:Int, b:Int) -> String in
        let c = a - b
        if c == 0 {
            return "They are the same."
        } else if c > 0 {
            return "The first one is larger."
        } else {
            return "The second one is larger."
        }
    }(4, 5) // 立即执行的闭包
    let comparingMethod = {
        (a:Int, b:Int) -> String in
        let c = a - b
        if c == 0 {
            return "They are the same."
        } else if c > 0 {
            return "The first one is larger."
        } else {
            return "The second one is larger."
        }
    }
    compareBy(a: 4, b: 4, comparingMethod)
    comparingMethod(8, 9)
    
    // 函数和闭包***
    // 函数即闭包,闭包即函数.函数能够用实际参数标签而闭包的实际参数标签为_,其他的功能,函数和闭包相同.能用函数还是尽量用函数,以便提高代码的可读性
    
    

    相关文章

      网友评论

          本文标题:7.闭包 Closures Swift官方文档——版纳的笔记

          本文链接:https://www.haomeiwen.com/subject/fpwucftx.html