您的位置:首页 > 移动开发 > Swift

10.Swift 中的闭包

2016-02-01 13:32 477 查看
在Objective-C中, 我们有block, 在Swift中, 我们有闭包, 两者之间基本上一致, 没有多大的区别, 非要说起不同, 也就是声明的语法有些差异, 还有一些特性上的差异, 下面让我们来看看.

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)
}


这里有个例子, 有兴趣的朋友可以自己去研究看看, 如果想看更加详细的内容, 可以去参考官方文档.

这次就讲到这里, 下次继续
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  objective-c 闭包 swift