设为首页 加入收藏

TOP

闭包(Closure)(二)
2017-10-09 13:35:04 】 浏览:5199
Tags:闭包 Closure
it as a trailing closure instead. A trailing closure is written after the function call’s parentheses, even though it is still an argument to the function. When you use the trailing closure syntax, you don’t write the argument label for the closure as part of the function call.

如果函数的最后一个参数是闭包,可以使用尾随闭包代替,举个例子:

func someFunctionThatTakesAClosure(closure: () -> Void) {
    // function body goes here
}

// Here's how you call this function without using a trailing closure:
//没有使用尾随闭包的函数调用情况
someFunctionThatTakesAClosure(closure: {
    // closure's body goes here
})

// Here's how you call this function with a trailing closure instead:
//使用了尾随闭包函数的调用情况
someFunctionThatTakesAClosure() {
    // trailing closure's body goes here
}

以数组的排序函数作为例子来看一下:

let numbers = [1, 3, 2, 4, 7, 8, 5]
let sortedNums = numbers.sorted(by: { $0 > $1 })    //没有使用尾随闭包,整个闭包写在sorted函数参数圆括号内,闭包内容多的话会显的很乱
let sortedNums = numbers.sorted() { $0 > $1 }    //使用尾随闭包,这样会使代码看起来很整洁

swift里还有一个规则,如果函数只有闭包一个参数,作为尾随闭包,可以把()去掉,使代码更为简洁,代码如下:

let numbers = [1, 3, 2, 4, 7, 8, 5]
let sortedNums = numbers.sorted(){ $0 > $1 }    //没有去掉"()"
let sortedNums = numbers.sorted { $0 > $1 }    //去掉"()"

5.闭包捕获值(Capturing Values)

A closure can capture constants and variables from the surrounding context in which it is defined.

闭包可以捕获包裹它的上下文所定义的常量和变量。

(1)全局函数

var number = 0
var add = {
    number += 1
    print(number)
}

add()    //1
add()    //2
add()    //3
print(number)    //3

从上面的代码可以看出来,闭包捕获的是值的引用,当闭包内修改闭包外的值,闭包外的值也会跟着改变。

(2)函数嵌套函数

func makeIncrementer(from start: Int, amount: Int) -> ()->Int {
    var number = start
    return {
        number += amount
        return number
    }
}

let incrementer = makeIncrementer(from: 0, amount: 1)
incrementer()  //1
incrementer()  //2
incrementer()  //3

函数makeIncrementer返回的是一个没有参数返回整数的函数(闭包),所以,常量incrementer其实就是一个函数。每次调用incrementer()都会执行闭包里面的操作,而闭包的上下文就是makeIncrementer函数。从这也可以看出来,函数既能当返回值,也可以做参数,在swift妥妥的一等公民,比在Object-C的功能强大多了。

(3)swift中closure(闭包)和Object-C中block的区别

//block
NSInteger number = 1;
NSMutableString *str = [NSMutableString stringWithString: @"hello"];
void(^block)() = ^{
  NSLog(@"%@--%ld", str, number);
};
[str appendString: @" world!"];
number = 5;
block();    //hello world!--1

//closure
var str = "hello"
var number = 1
let block = {
    print(str + "--" + " \(number)")
}
str.append(" world!")
number = 5
block()    //hello world!--5

一句话来说,block内部会对值类型做一份复制,并不指向之前的值的内存地址,而对于对象类型则会指向对象当前的内存地址,所以修改number时,block里的number数值不变,而修改字符串时,block里的字符串则改变了;closure则默认给外部访问的变量加上了__block修饰词的block。至于闭包里的循环引用,可以看一下OC与Swift闭包对比总结这篇文章。

6.逃逸闭包(Escaping Closures)

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

逃逸闭包,指的是当一个函数有闭包作为参数,但是闭包的执行比函数的执行要迟。通俗来说,这个闭包的作用域本来是在当前函数里面的,然后它要逃出这个作用域,不想和函数同归于尽。那么闭包怎么逃逸呢?最简单的方法是把闭包赋值给外面的变量,举个例子:

var completionHandlers: [() -> Void] = []
//必须加上@escaping,不然编译会报错
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure {
    print("hello
首页 上一页 1 2 3 下一页 尾页 2/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇Swift的Guard语句 下一篇Swift语言中与C/C++和Java不同的..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目