Block 存储域 copy入堆的作用

myBlk   clang后转换为  Blcok的结构体类型的自动变量

160341_bBp8_2472425.png

 

 

__block 变量a   clang 后转换成  __block变量的结构体类型的自动变量

160620_dHVV_2472425.png

 

他们都在存储在栈区上

 

 

_NSConcreteStackBlock     栈

_NSConcreteGlobalBlock   全局区(静态区)  准确说是 .data区 .data区是放已被初始化的全局、静态)

_NSConcreteMallocBlock   堆

 

什么样的Block 设置在全局区、什么样的在栈区??

没有引用自动变量的block叫做NSGlobalBlock, (引用全局或者外部变量还是NSGlobalBlock)

其余Block生成的Blcok 为 NSStackBlock类对象, 且设置在栈区

 

配置在堆区上的Block 类 何时使用?

这正是上一篇博客留下的问题:Blcok 超出变量作用域可存在的原因?

配置在栈区的Block, 其作用域结束时,该Block就被废弃了。 __block 也是配置在栈区,作用域结束时同样也会被废弃。

全局区的block 作用域广,所以不会有这种问题,但是全局Block 是不捕获自动变量的。用的也少。

 

那怎么解决栈区Block 过了作用域销毁的问题呢?

Blocks 提供了将Block 和 __block变量 从栈上 复制到 堆上 的方法 来解决这个问题。将栈上的Blcok 复制到堆上,这样即使Block的变量作用域结束了,堆上的Block还可以继续存在。

160738_ecyf_2472425.png

 

这就解决了过了作用域销毁的问题

 

在看__forwarding 的问题, __block变量用结构体成员变量__forwarding可以实现无论__block变量配置在栈上还是堆上,都能正确的访问__block结构体变量。

 

 

栈区block copy 后从栈区到堆区

全局block copy 后什么也不做

堆区block copy 后引用计数增加

所以 不管Block配置在何处,用copy都不会引起任何问题。但是copy是相当消耗CPU资源的,当Block在栈区可以使用时,就不要copy进堆区。

且在 ARC中多次copy 也没有任何问题。 ARC中大部分情况系统都帮你做了copy,只有 向方法或函数的参数传递Block时,系统不会自动copy。 但是如果在方法或函数中适当地复制了传递过来的参数,就不用在调用方法或函数前手动复制了。比如有些方法就为我们这么设计了:

1.cocoa框架的方法且方法名中含有usingBlock的方法

2.GCD 的API

具体举例:NSArray类的 enumerateObjectsUsingBlock 实例方法 

               GCD的 dispatch_async函数 

都不需要手动复制。

 

 

需要手动复制的方法:

NSArray initWithObjects 实例方法上传递Block是需要手动复制

174006_zJ1h_2472425.png

原因是:block是栈区block 过了作用域,block就销毁了。

解决办法:将block 复制到堆区。

174212_uQFY_2472425.png

 

 

转载于:https://my.oschina.net/u/2472425/blog/1527613

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值