block原理
block原理
block的本质是一个结构体,包含引用的外部变量及一个需要执行的函数的函数指针,在内存中可以有三个位置,即堆上、栈上和全局区(静态区)。当block中没有引用外部变量时,block的位置在全局区,当block中访问外部变量时,MRC下block默认在栈区,ARC下block默认会从栈区复制到堆区。
另外,block在生成对应的结构体时,如果引用的外部变量是strong类型的,那么在结构体内部生成的对应成员变量就是strong类型的;如果引用的外部变量是weak类型的,那么在结构体内部生成的对应的成员变量就是weak类型的;如果是基本类型的,那么生成的对应的成员变量就是基本类型的。block的函数在执行时,会在函数体内部创建局部变量,赋值成对应的block结构体内的成员变量,然后再用这些局部变量去做对应的操作,这也是普通情况下(外部变量不加__block关键字)block内部不能改变外部变量的原因。所以block在创建的时候实际上就已经对其中引用的外部变量有内存操作了(strong类型的引用计数会加1),在block的函数体执行过程当中,外部变量的引用计数也会有相应的增减。
__block关键字原理
通常情况下,block的函数体中是不能更改引用的外部变量的值的(但是可以改这个变量的某个属性值,如果这个变量是个OC类型的变量,因为对象还是同一个对象),但是如果外部变量用了__block关键字修饰,那么block函数体内部就可以更改这个外部变量的值。原理是在加了__block关键字之后,这个变量会变成一个结构体中的一个成员变量,之后我们再访问这个外部变量的时候实际上是在访问这个结构体里对应的成员变量。结构体中会有一个forwarding指针,访问成员变量时都会通过这个forwarding指针,当这个变量在栈上时forwarding指针指向结构体自身,当这个变量被复制到堆上时栈上的结构体的forwarding指针指向堆上的这个结构体,堆上的结构体的forwarding指针还是指向自身,forwarding指针的作用就是在操作外部变量时,无论是通过栈上的结构体还是堆上对应的结构体,都能够操作同一个外部变量(即堆上的结构体中的成员变量)。
举个例子:
-(void)viewDidLoad {
__block int a = 1; //栈上的变量结构体(简称a结构体)
a++; // a结构体->forwarding->a++;这时候forwarding指向的是自己
self.myBlock = ^{//a结构体被赋值给block结构体中的成员变量,假设为a1结构体
a++; //block结构体->a1结构体->fowrding->a++;
};
a++; //a结构体->fowrding->a++; 这时候forwarding指向的是堆上的结构体
}
-(IBAction)clickButton {
self.myBlock(); //block结构体->a1结构体->fowrding->a++;
}
原理很简单:就是block结构体会创建内部成员变量保存外部变量,当外部变量被__block关键字修饰时会生成一个对应的变量结构体,block结构体对应的内部成员变量会变成这个变量结构体。(相当于是block结构体保存了__block修饰的外部变量的一个间接引用)
block原理的更多相关文章
- 转:Block原理及引用循环问题
2010年WWDC发布iOS4时Apple对Objective-C进行了一次重要的升级:支持Block.说到底这东西就是闭包,其他高级语音例如Java和C++已有支持,第一次使用Block感觉满简单好 ...
- 深入浅出-iOS Block原理和内存中位置
Posted by 微博@Yangsc_o 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 #简介 今天回顾一下blcok,基本 ...
- iOS之Block总结以及内存管理
block定义 struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(v ...
- iOS之block,一点小心得
作为一个iOS开发程序员,没用过block是不可能的.这次我探讨的是block原理,但是有些更深层次的东西,我也不是很清楚,以后随着更加了解block将会慢慢完善. 第一个问题,什么是block? 我 ...
- block注意事项
1.block的声明和注意事项 #import "ZYViewController.h" @interface ZYViewController () @end /*用typede ...
- fir.im Weekly - 一切从知识重构开始
一年之计在于春,大自然开始了新元素的重构.你的知识库是否也该重构更新呢? 本期 fir.im Weekly 包含最新的Android.iOS 开发工具.源码和好玩的UI 动画分享,希望对你有用. Sw ...
- POJ 1523 (割点+连通分量)
题目链接:http://poj.org/problem?id=1523 题目大意:连通图,找图中割点,并计算切除该割点后,图中的连通分量个数. 解题思路: POJ的数据很弱. Tarjan法求割点. ...
- MyQQ 前言
从接触IOS以来也将近8个月了,学习了不少知识. 看了一系列的书籍如: <objective-c 开发入门>--语法介绍,学习一门语言是开发的基础.所以这是我大致对语法语句学习的锻炼地方, ...
- ARC下需要注意的内存管理
ARC下需要注意的内存管理 2016/04/03 · iOS开发 · 内存管理 分享到:1 原文出处: 一不(@luoyibu) 之前发了一篇关于图片加载优化的文章,还是引起很多人关注的,不过也 ...
随机推荐
- Java中关于大小写字母的转换
方法一: 大小写字母在ascii码表中相减的值为32 故可将字符串转车字符数组 小写转大写减32 大写转小写加32 String s= "good"; char[] c = s.t ...
- ZBrush常用3D术语
转自:http://www.zbrushcn.com/jichu/zbrush-cy-3dsys.html Polygon(多边形) 多边形是一种形状,通过在3D空间连接几个点而创建,最简单的形式就是 ...
- SpringMVC 注解详解
SpringMVC常用注解说明 @Bean, @Configuration表示基于Java配置的类@Bean除了配置在@Configuration,也可以在@Component定义,此时没有特殊意义, ...
- mac gcc develop
1:check version gcc -v / g++ -v 2:compile gcc *.c / g++ *.cpp outfile: a.out 3:excute ./a.out ...
- python文件相关
文件操作基本流程初探 f = open('chenli.txt') #打开文件 first_line = f.readline() print('first line:',first_line) #读 ...
- 网络基础和python(二)
一,五层协议 应用层 端口 传输层 tcp\udp 网络层 ipv4\6 数据链路层 ethernet 物理层 mac 二:什么是变量? 变量:核心在于变和量儿字,变->变 ...
- OpenStack Nova虚拟机创建流程解析
https://yikun.github.io/2017/09/27/OpenStack-Nova%E8%99%9A%E6%8B%9F%E6%9C%BA%E5%88%9B%E5%BB%BA%E6%B5 ...
- HTTP请求返回值所代表的含义
一些常见的状态码为: 200 - 服务器成功返回网页(表示请求成功) 404 - 请求的网页不存在(可能是网络的问题,也可能是网页没办法访问不代表网页不存在) 503 - 服务器超时(服务器故障) 下 ...
- 为什么TCP比UDP可靠真正原因,以及并发编程的基础问题
一 为什么TCP协议比UDP协议传输数据可靠: 我们知道在传输数据的时候,数据是先存在操作系统的缓存中,然后发送给客户端,在客户端也是要经过客户端的操作系统的,因为这个过程涉及到计算机硬件,也就是物 ...
- vue2.0自定义指令
前面一片文章说了vue2.0过滤器,其实自定义指令跟过滤器非常相似,单就定义方式而言,其与过滤器完全一致,分为局部指令,和全局指令.不过就是filter改为directive的区别. 过滤器一般用于对 ...