接上回。
一、上篇提到swift闭包的问题,估计和block同本同源。查了写别人写的关于闭包的,都会提到闭包的一个特点。捕获值。
解释:闭包可以在其被定义的上下文中捕获常量或变量。即使定义这些常量和变量的原作用域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
这个怎么理解?有什么用?
其实就是把B函数把闭包A作为返回值传递出去,在全局中获得了A闭包,但是A闭包可以操作B函数的局部变量,这样就实现了捕获局部变量。swift 的例子也简单,为了省事,这次接着用OC的block说明这个问题。
PS:OC快淘汰了,赶紧看swift啦啦啦啦。
上文说到,如果一个函数作为参数或者返回值传到另外一个函数里,那么这个函数就成了block。block如果作为参数传递,就实现了回调的功能,block如果作为返回值返回出来,就实现了捕获值的功能。这就是本文的重点。
- (void(^)())testFunction3WithParameter:(NSString *)title{
NSLog(@"方法3的实现 -- %@", title);
__block int index = 0;
void(^block)() = ^(){
index = index + 1;
NSLog(@"block的实现--%d", index);
};
return block;
}
定义并实现了一个函数,可以看到返回值比较特殊,是个block,也就是返回了一个函数,不是常见的void或者int等等。
和回调不同的是,block的定义实现写在了一起,调用依然和实现分开。
在这个函数内部,我定义了一个int类型,并定义实现了一个block,在实现代码中,我给这个局部变量index每次加1.最后把block返回出去。
接下来改调用这个函数了:
void(^myBlock)() = [self testFunction3WithParameter:@"方法3"];
myBlock();
myBlock();
myBlock();
由于这个函数返回值是个函数,所以必须用函数接收,定义了一个函数,叫block,接受了这个方法的返回值。
前面说到,我把block的定义和实现写在了一起,还没有调用,所以在这里接收到block后,再调用,第一次调用,执行block的大括号里面的代码,打印1,再执行打印2,再执行打印3,这就是捕获值。block捕获到了它所在的函数的局部变量,并在全局中调用,并且这个值保存在内存中,相当于成了要给全局变量,每次操作都保留了最新结果。
所以block也有这个捕获值的特点,和闭包一样,虽然还不清楚有啥卵用。
二、block也是引用类型(说不清了,我也不懂)
因为函数也是引用类型?这么解释?
PS:值类型和引用类型
// 值类型:指的是当一个变量赋值给另外一个变量的时候, 是copy一个副本
// 两个变量之间互不影响, 也就是说, 另外一个变量的值改变, 不会影响到另外一个变量
// 也就是传的只是一个值, 不是一个引用(地址)
int a = 0
int b = a
b = 2
最后打印结果是a = 0, b = 2;b对a没有影响
// 闭包和函数都是引用类型
// 引用类型:指的是当引用类型变量赋值给另外一个变量的时候, 其实两个变量指的都是同一个内容
// 当其中一个变量修改了这个内容, 另外一个变量也会跟着改变
对于block,代码如下
void(^myBlock)() = [self testFunction3WithParameter:@"方法3"];
myBlock();
myBlock();
myBlock();
void(^myBlock1)() = myBlock;
myBlock1();
再用个相同类型的block=myBlock,最后打印结果是4,说明是同一个对象,所以说block也是引用类型。