10.Swift 中的闭包
2016-02-01 13:32
477 查看
在Objective-C中, 我们有block, 在Swift中, 我们有闭包, 两者之间基本上一致, 没有多大的区别, 非要说起不同, 也就是声明的语法有些差异, 还有一些特性上的差异, 下面让我们来看看.
这是一个排序的例子, 再想想, 貌似没有了更好的简洁方式了吧, 但这一切也只是在没有闭包之前, 下面让我们来看看闭包的强大之处.
这个就是闭包表达式的语法, 完全不需要另外新建一个函数, 就可以完成排序的操作.
这也是一种闭包的写法, Swift中有一个特性就是会根据上下文去推断类型, 而闭包也是可以如此的, 所以我们可以直接这么写.
在闭包里, 单行的闭包是可以不需要写return关键字的, 默认就会返回.
这种写法也是闭包的表达式, 不需要写参数名, 就可以直接排序.
这种写法也是闭包的表达式, 完全不需要任何参数, 直接写明一个运算符就可以完成排序, 但这种写法不太好, 只能完成一些比较简单的排序.
map的用法和For-in有些类似, 它会映射数组的元素, 然后遍历, 直到遍历到最后一个元素为止.
这里的customerProvider就相当于我们自定义的一个闭包函数, 虽然在闭包里, 已经移除了一个元素, 但该闭包并没有被调用, 所以元素不会被移除.
所谓的逃逸闭包就是当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸, 也就是说, 在函数外部可访问, 而非逃逸闭包就是只能在函数内部访问, 一旦函数运行结束, 闭包也就结束了.
这里有几个关键字: @noescape, @autoclosure, @autoclosure(escaping)
@noescape关键字来标注的闭包, 就会变成非逃逸闭包, 说明该闭包不能被函数外部所访问.
@autoclosure关键字来标注的参数, 则会自动把参数转变成自动闭包, 注意@autoclosure关键也是含有@noescape关键的特性, 所以用@autoclosure来标注的闭包参数是不可以逃逸的.
@autoclosure(escaping)关键字来标注的参数, 则会自动把参数转变成自动闭包, 并且可逃逸.
这里有个例子, 有兴趣的朋友可以自己去研究看看, 如果想看更加详细的内容, 可以去参考官方文档.
这次就讲到这里, 下次继续
1.前言
在讲闭包之前, 我们来看看一个简单的例子:let array = [1, 2, 3, 5, 3, 10, 20, 30] func backwards(s1: Int, s2: Int) -> Bool { return s1 > s2 } var reversed = array.sort(backwards) print(reversed) // 打印出来的结果: // [30, 20, 10, 5, 3, 3, 2, 1]
这是一个排序的例子, 再想想, 貌似没有了更好的简洁方式了吧, 但这一切也只是在没有闭包之前, 下面让我们来看看闭包的强大之处.
2.闭包表达式语法
reversed = array.sort( { (s1: Int, s2: Int) -> Bool in return s1 > s2 } )
这个就是闭包表达式的语法, 完全不需要另外新建一个函数, 就可以完成排序的操作.
3.根据上下文推断类型
reversed = array.sort({s1, s2 in return s1 > s2})
这也是一种闭包的写法, Swift中有一个特性就是会根据上下文去推断类型, 而闭包也是可以如此的, 所以我们可以直接这么写.
4.单表达式闭包隐式返回
reversed = array.sort({ s1, s2 in s1 > s2})
在闭包里, 单行的闭包是可以不需要写return关键字的, 默认就会返回.
5.参数名称缩写
reversed = array.sort( { $0 > $1 } )
这种写法也是闭包的表达式, 不需要写参数名, 就可以直接排序.
6.运算符函数
reversed = array.sort(>)
这种写法也是闭包的表达式, 完全不需要任何参数, 直接写明一个运算符就可以完成排序, 但这种写法不太好, 只能完成一些比较简单的排序.
7.尾随闭包
所谓的尾随闭包, 就是自己声明一个闭包函数, 在别的地方去调用.func someFunctionThatTakesAClosure(closure: () -> Void) { // 闭包函数体 } // 写法一 someFunctionThatTakesAClosure({ // 闭包函数体 }) // 写法二 someFunctionThatTakesAClosure() { // 闭包函数体 }
8.map函数
在Swfit原生当中, 有一个叫做map(_:)的函数, 它也是一个闭包类型, 下面让我们来看看.let people = ["ZhangSan", "LiSi", "WangWu"] let person = people.map { (var name) -> String in print(name) return name }
map的用法和For-in有些类似, 它会映射数组的元素, 然后遍历, 直到遍历到最后一个元素为止.
9.自动闭包和闭包的延迟操作
var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9] print(numberArray.count) // 输出的结果为: 9 let customerProvider = { numberArray.removeAtIndex(0) } print(numberArray.count) // 输出的结果为: 9 print("Now serving \(customerProvider())!") // 输出的结果为: Now serving 1! print(numberArray.count) // 输出的结果为: 8
这里的customerProvider就相当于我们自定义的一个闭包函数, 虽然在闭包里, 已经移除了一个元素, 但该闭包并没有被调用, 所以元素不会被移除.
10.闭包的其他知识
这里还有一个叫做逃逸闭包, 和非逃逸闭包的概念:所谓的逃逸闭包就是当一个闭包作为参数传到一个函数中,但是这个闭包在函数返回之后才被执行,我们称该闭包从函数中逃逸, 也就是说, 在函数外部可访问, 而非逃逸闭包就是只能在函数内部访问, 一旦函数运行结束, 闭包也就结束了.
这里有几个关键字: @noescape, @autoclosure, @autoclosure(escaping)
@noescape关键字来标注的闭包, 就会变成非逃逸闭包, 说明该闭包不能被函数外部所访问.
@autoclosure关键字来标注的参数, 则会自动把参数转变成自动闭包, 注意@autoclosure关键也是含有@noescape关键的特性, 所以用@autoclosure来标注的闭包参数是不可以逃逸的.
@autoclosure(escaping)关键字来标注的参数, 则会自动把参数转变成自动闭包, 并且可逃逸.
var numberArray = [1, 2, 3, 4, 5, 6, 7, 8, 9] func someFunctionWithNoescapeClosure(@noescape closure: () -> Void) { closure() } func serveCunstomer(@autoclosure customerProvider: () -> Int) { print("Now serving \(customerProvider())!") } var customerProviders: [() -> Int] = [] func collectCustomerProviders(@autoclosure(escaping) customerProvider: () -> Int) { customerProviders.append(customerProvider) }
这里有个例子, 有兴趣的朋友可以自己去研究看看, 如果想看更加详细的内容, 可以去参考官方文档.
这次就讲到这里, 下次继续
相关文章推荐
- 深入理解PHP之匿名函数
- Apple Swift学习教程
- 介绍 Fedora 上的 Swift
- Ruby中使用Block、Proc、lambda实现闭包
- LUA中的闭包(closure)浅析
- Lua中的闭包学习笔记
- C#中函数的创建和闭包的理解
- 深入理解javascript作用域和闭包
- javascript作用域和闭包使用详解
- 谈谈JavaScript中的函数与闭包
- 细品javascript 寻址,闭包,对象模型和相关问题
- JavaScript中的闭包原理分析
- 浅谈javascript中的闭包
- 学习javascript的闭包,原型,和匿名函数之旅
- javascript 闭包详解
- JavaScript 匿名函数和闭包介绍
- JavaScript 闭包深入理解(closure)
- 深入理解JavaScript 闭包究竟是什么
- 谈谈我对JavaScript原型和闭包系列理解(随手笔记8)