Swift-闭包

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

import UIKit

var str = "Hello, playground"
/*
 在函数 章节中介绍的全局和嵌套函数实际上也是特殊的闭包,闭包采取如下三种形式之一:
 
 全局函数是一个有名字但不会捕获任何值的闭包
 嵌套函数是一个有名字并可以捕获其封闭函数域内值的闭包
 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包
 Swift 的闭包表达式拥有简洁的风格,并鼓励在常见场景中进行语法优化,主要优化如下:
 
 利用上下文推断参数和返回值类型
 隐式返回单表达式闭包,即单表达式闭包可以省略return关键字
 参数名称缩写
 尾随(Trailing)闭包语法
 */

//闭包表达式语法有如下一般形式:
/*  { (parameters) -> returnType in
statements
}
*/

//闭包表达式语法可以使用常量、变量和inout类型作为参数,不提供默认值。 也可以在参数列表的最后使用可变参数。 元组也可以作为参数和返回值。
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]

//func backwards(s1: String, s2: String) -> Bool {
//    return s1 > s2
//}
//var reversed = names.sort(backwards)

var reversed = names.sort({ (s1: String, s2: String) -> Bool in
    return s1 > s2
})

//根据上下文推断类型
/*
 因为排序闭包函数是作为sort(_:)方法的参数进行传入的,Swift可以推断其参数和返回值的类型。 sorted期望第二个参数是类型为(String, String) -> Bool的函数,因此实际上String,String和Bool类型并不需要作为闭包表达式定义中的一部分。 因为所有的类型都可以被正确推断,返回箭头 (->) 和围绕在参数周围的括号也可以被省略:
 */

//reversed = names.sort( { s1, s2 in return s1 > s2 } )


//单表达式闭包隐式返回
//单行表达式闭包可以通过隐藏return关键字来隐式返回单行表达式的结果
//reversed = names.sort( { s1, s2 in s1 > s2 } )


//参数名称缩写
//Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。
/*
 如果您在闭包表达式中使用参数名称缩写,您可以在闭包参数列表中省略对其的定义,并且对应参数名称缩写的类型会通过函数类型进行推断。 in关键字也同样可以被省略,因为此时闭包表达式完全由闭包函数体构成:
 */

reversed = names.sort( { $0 > $1 } )


//运算符函数
/*
 实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。 Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:
 */
reversed = names.sort(>)


//尾随闭包
/*
 如果您需要将一个很长的闭包表达式作为最后一个参数传递给函数,可以使用尾随闭包来增强函数的可读性。 尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
 */

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // 函数体部分
}

// 以下是不使用尾随闭包进行函数调用
someFunctionThatTakesAClosure({
    // 闭包主体部分
})

//注意: 如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把()省略掉
// 以下是使用尾随闭包进行函数调用
someFunctionThatTakesAClosure() {
    // 闭包主体部分
}

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

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

//捕获值
/*
 闭包可以在其定义的上下文中捕获常量或变量。 即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值
 
 Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。 嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量
 */

func makeIncrementor(forIncrement amount: Int) -> () -> Int {
    var runningTotal = 0
    func incrementor() -> Int {
        runningTotal += amount
        return runningTotal
    }
    return incrementor
}
/*
 注意: 为了优化,Swift可能会捕捉和保存一份对值的拷贝,如果这个值是不可变或是在闭包外的。 Swift同样负责被捕捉的所有变量的内存管理,包括释放不被需要的变量。
 */
let incrementByTen = makeIncrementor(forIncrement: 10)
incrementByTen()
incrementByTen()

/*
 如果您创建了另一个incrementor,其会有一个属于自己的独立的runningTotal变量的引用。 下面的例子中,incrementBySevne捕获了一个新的runningTotal变量,该变量和incrementByTen中捕获的变量没有任何联系
 */

let incremenSecond = makeIncrementor(forIncrement: 7)
incremenSecond()
incremenSecond()

incrementByTen()

/*
 注意: 如果您将闭包赋值给一个类实例的属性,并且该闭包通过指向该实例或其成员来捕获了该实例,您将创建一个在闭包和实例间的强引用环。 Swift 使用捕获列表来打破这种强引用环。更多信息,请参考 闭包引起的循环强引用。
 */


//闭包是引用类型
/*
 无论您将函数/闭包赋值给一个常量还是变量,您实际上都是将常量/变量的值设置为对应函数/闭包的引用。 上面的例子中,incrementByTen指向闭包的引用是一个常量,而并非闭包内容本身。
 */

//如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包
let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值