Swift闭包概念与常见使用场景总结

·Swift 闭包

闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。

Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 匿名函数比较相似。

全局函数和嵌套函数其实就是特殊的闭包。

闭包的形式有:

全局函数

嵌套函数

闭包表达式

有名字但不能捕获任何值。

有名字,也能捕获封闭函数内的值。

无名闭包,使用轻量级语法,可以根据上下文环境捕获值。

Swift中的闭包有很多优化的地方:

  1. 根据上下文推断参数和返回值类型
  2. 从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
  3. 可以使用简化参数名,如$0, $1(从0开始,表示第i个参数...)
  4. 提供了尾随闭包语法(Trailing closure syntax)

闭包表达式

闭包表达式是一种利用简洁语法构建内联闭包的方式。
闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。

sort 函数
Swift 标准库提供了名为sort的函数,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。

排序完成后,sort(_:)方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组,原数组不会被sort(_:)方法修改。

sort(_:)方法需要传入两个参数:

  1. 已知类型的数组
    2.   闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回true,反之返回false。

参数名称缩写
Swift 自动为内联函数提供了参数名称缩写功能,您可以直接通过$0,$1,$2来顺序调用闭包的参数。

import Cocoa

 

let names = ["AT", "AE", "D", "S", "BE"]

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

print(reversed)

$0和$1表示闭包中第一个和第二个String类型的参数。

以上程序执行输出结果为:        

["S", "D", "BE", "AT", "AE"]

运算符函数

实际上还有一种更简短的方式来撰写上面例子中的闭包表达式。

Swift 的String类型定义了关于大于号 (>) 的字符串实现,其作为一个函数接受两个String类型的参数并返回Bool类型的值。 而这正好与sort(_:)方法的第二个参数需要的函数类型相符合。 因此,您可以简单地传递一个大于号,Swift可以自动推断出您想使用大于号的字符串函数实现:

import Cocoa

 

let names = ["AT", "AE", "D", "S", "BE"]

var reversed = names.sort(>)

print(reversed)

以上程序执行输出结果为:        

["S", "D", "BE", "AT", "AE"]

尾随闭包

尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。

注意:如果函数只需要闭包表达式一个参数,当您使用尾随闭包时,您甚至可以把()省略掉。

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

捕获值

闭包可以在其定义的上下文中捕获常量或变量。

即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。

Swift最简单的闭包形式是嵌套函数,也就是定义在其他函数的函数体内的函数。

嵌套函数可以捕获其外部函数所有的参数以及定义的常量和变量。

闭包是引用类型。

 

总结:闭包的常见使用场景

目前基于Swift 3.0+ 版本总结闭包的常见使用场景

// 1.作为变量(类中的属性):

// var 闭包名称: (参数列表) -> 返回类型

var closureName1: (_ name: String, _ age: Int) -> String

 

// 2.作为可选的变量(类中的属性):

// var closureName: ((parameterTypes) -> returnType)?

var closureName2: ((_ name: String, _ age: Int) -> String)?

 

// 3.作为类型别名(闭包类型):

// typealias closureType = (parameterTypes) -> returnType

typealias closureType = (_ name: String, _ age: Int) -> String

 

// 4.作为常量(类中的属性):

// let closureName: closureType = 闭包表达式

let closureName3: closureType = { (_ name: String, _ age: Int) -> String in

    return "My name is \(name), age is \(age)"

}

closureName3("Abnerzj", 10)

 

// 5.定义函数时作为函数的参数:

// 5.1 func 函数名(参数名: 闭包类型)

func closureFuncName(closureParameterName: closureType) -> Void {

    // 函数体部分

}

 

// 5.2 func 函数名(参数名: 闭包表达式)

func closureFuncName2(closureParameterName: (_ name: String, _ age: Int) -> String) -> Void {

    // 函数体部分

}

 

// 6.调用函数时作为函数的参数:完整的闭包格式

// 函数名(参数名: 闭包表达式)

// 函数名(参数名: { 闭包参数列表 -> 闭包返回值 in 闭包函数体 })

closureFuncName(closureParameterName: {

    (_ name: String, _ age: Int) -> String in

    return "My name is" + name + ", age is \(age)"

})

 

// 7.调用函数时作为函数的参数:根据上下文推断类型:

// 函数名(参数名: { 实参名1, 实参名2 in 闭包函数体 })

closureFuncName(closureParameterName: {

    name, age in

    return "My name is" + name + ", age is \(age)"

})

 

// 8.调用函数时作为函数的参数:单行表达式闭包隐式返回,可以隐藏return关键字

// 函数名(参数名: { 实参名1, 实参名2 in 闭包函数体 })

closureFuncName(closureParameterName: {

    name, age in "My name is" + name + ", age is \(age)"

})

 

// 9.调用函数时作为函数的参数:参数名称缩写($0,$1,$2...来顺序代替参数列表中的参数名)

// 函数名(参数名: { 闭包函数体 })

closureFuncName(closureParameterName: {

    "My name is \($0), age is \($1)"

})

 

// 10.调用函数时作为函数的参数:尾随闭包(作为函数的最后一个参数),不是函数的唯一一个参数时

// 函数名() { 闭包函数体 }

closureFuncName() {

    "My name is \($0), age is \($1)"

}

 

// 11.调用函数时作为函数的参数:尾随闭包(作为函数的最后一个参数),是函数的唯一一个参数时

// 函数名 { 闭包函数体 }

closureFuncName {

    "My name is \($0), age is \($1)"

}

 

// 12.调用函数时传入一个闭包函数作为函数的参数

// 函数名(参数名: 闭包函数名)

func closureFunc(_ name: String, _ age: Int) -> String {

    return name + "\(age)"

}

closureFuncName(closureParameterName: closureFunc)

 

// 13.调用函数时作为函数的参数:循环强引用

// 函数名(参数名: { [弱引用或无主引用列表] 闭包参数列表 -> 闭包返回值 in 闭包函数体 })

// 第一种:推荐

closureFuncName(closureParameterName: {

    [weak self] (_ name: String, _ age: Int) -> String in

    self?.view.backgroundColor = UIColor.red

    return "My name is" + name + ", age is \(age)"

})

 

// 第二种:

weak var weakself = self

closureFuncName(closureParameterName: {

    (_ name: String, _ age: Int) -> String in

    weakself?.view.backgroundColor = UIColor.red

    return "My name is" + name + ", age is \(age)"

})

 

// 第三种:

closureFuncName(closureParameterName: {

    [unower self] (_ name: String, _ age: Int) -> String in

    self?.view.backgroundColor = UIColor.red

    return "My name is" + name + ", age is \(age)"

})

 

 

上面是我对Swift闭包的理解与总结。欢迎各位博友学习浏览,如在哪里总结的不到位希望各位朋友提出更好的建议。

此博文只是为了与更多博友们交流学习心得,如需转载请注明出处。 谢谢!

关于闭包的总结就到此处啦! 觉得此博文整理的好的话,就给个赞吧。。。 感谢大家的支持!!!

 

posted on 2016-11-26 16:49  随缘相识-(志同道合)  阅读(668)  评论(0编辑  收藏  举报

导航