Block的循环引用

Block的使用

1.概念:block实质就是一个匿名函数块,经过编译器的编译后,最终为一个函数,block也是objective-c中的对象,根据block对象创建时所处的数据区不同而进行区别:

在栈上创建的Block对象,_NSConcreteStackBlock

在堆上创建的Block对象,_NSConcreteMallocBlock

在全局数据区的Block对象,_NSConcreteGlobalBlock

block可以截取自动变量,所谓自动变量就是不是全局或者静态的变量,在当前上下文范围内,Block块可以捕捉到它的一个瞬间值,所谓瞬间值就是某一时刻的值,当我们在外面改变了变量的值,block内部仍然是之前某个瞬间的值,不会改变,譬如:

// 声明一个无返回值、无参数的block变量

​ __block int i = 10; // 如果block内部需要改变I的值,那么这里就应该给添加个__block,这时的变量成为__block变量

​ NSMutableArray *arr = [[NSMutableArray alloc] initWithObjects:@”1”,@”2”, nil];

​ NSLog(@”arr count:%ld”,arr.count);

​ void (^blockType)(void) = ^{

​ NSLog(@”In block,i = %d”,i); // 这里block截或了外部的自动变量,保存了”瞬间值”

​ i = 100;

​ NSLog(@”after change,i = %d”,i);

​ [arr removeObjectAtIndex:0];

​ };

​ i = 20;// 这里改变i的值,看下block中是否会打印这个i为20,虽然这里改变了i的值,但是外部的i是不会受到影响的

​ NSLog(@”out block,i = %d”,i);

​ blockType();

​ NSLog(@”arr count:%ld”,arr.count);

Block的存储区域:

void (^blk)(void) = ^ {

​ NSLog(@”Global Block”);

};

int main(int argc, const char * argv[]) {

​ @autoreleasepool {

// BlockManager *manager = [[BlockManager alloc] init];

// [manager statementParameter];

​ //打印的是NSGlobalBlock

​ blk();

​ NSLog(@”%@”,[blk class]);

​ void (^blk1)(void) = ^ {

​ NSLog(@”Global Block”);

​ };

​ // 没有捕获了自动变量,打印的是NSGlobalBlock

​ blk1();

​ NSLog(@”%@”,[blk1 class]);

​ // 捕获了自动变量,打印的是NSMallocBlock

​ int i = 1;

​ void (^captureBlock)(void) = ^{

​ NSLog(@”Capture:%d”,i);

​ };

​ captureBlock();

​ NSLog(@”%@”,[captureBlock class]);

​ }

​ return 0;

}

Block复制:

配置在栈上的Block,如果其所属的栈作用域结束,该Block就会被废弃,对于超出Block作用域仍需使用Block的情况,Block提供了将Block从栈上复制到堆上的方法来解决这种问题,即便Block栈作用域已结束,但被拷贝到堆上的Block还可以继续存在。

在ARC有效时,大多数情况下编译器会进行判断,自动生成将Block从栈上复制到堆上的代码,以下几种情况栈上的Block会自动复制到堆上

  • 调用Block的copy方法
  • 将Block作为函数返回值时
  • 将Block赋值给__strong修改的变量时
  • 向Cocoa框架含有usingBlock的方法或者GCD的API传递Block参数时

之前在栈上创建的block截取了自动变量i,但是实际却显示的是NSMallocBlock类,就是因为这个Block对象赋值给了_strong修饰的变量captureBlk(_strong是ARC下对象的默认修饰符)

因为上面四条规则,在ARC下其实很少见到_NSConcreteStackBlock类的Block,大多数情况编译器都保证了Block是在堆上创建的

3.使用__block发生了什么?

Block捕获的自动变量添加__block说明符,就可以在Block内读写该变量,也可以在原来的栈上读写该变量.

__block保证了栈上和Block内(通常在堆上)可以访问和修改“同一个变量”,__block是如何实现这一功能的?

__block发挥作用的原理:将栈上用__block修饰的自动变量封装成一个结构体,让其在堆上创建,以方便从栈上或堆上访问和修改同一份数据。

Block的循环引用

参考:https://www.jianshu.com/p/d28a5633b963

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值