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) 之前发了一篇关于图片加载优化的文章,还是引起很多人关注的,不过也 ...
随机推荐
- [UE4]场景加载界面
就可以这样就可以了,当另外一个场景成功打开后,场景加载界面也会自动消失(因为这是加载界面是添加到当前场景). 加上delay是为了在小场景测试的时候可以方便看到加载场景,避免场景加载过快看不到,不加的 ...
- ACCESS常用数字类型的说明和取值范围
下面是ACCESS常用数字类型的说明和取值范围列表明供参考 数字类型 范围 Byte(字节) 介于 0 到 255 之间的整型数. Integer ...
- [电脑知识点]Excel取消受保护视图
- SPOJ COT3 - Combat on a tree
/* 考虑直接使用暴力来算的话 SG[i]表示以i为根的子树的SG值, 然后考虑枚举删除那个子树节点, 然后求拆成的树的sg异或值, 求mex即可 复杂度三次方 然后考虑尝试 整体来做 发现对于每次子 ...
- isNAN的使用方法及介绍
NaN为 Not a Number isNaN()函数在接到一个值后,会尝试将这个值转换为数值. alert(isNaN(NaN)); //true alert(isNaN(25)); //false ...
- websocket如何设置?
根据之前写的步骤到当前的websocket设置 一.websocket设置: 1)在线程租下右键单击选择Sampler如图: 2)进行它的设置 2.保存 3.添加查看结果数和聚合报告(此处不详细说明, ...
- 网易微专业 UI设计师
网易云课堂的UI设计师微专业,需要的留言
- 性能测试day02_预习知识
在进入第二天的学习之前,我想我们需要提前先了解一下基础的知识,所以这一篇主要讲解的就是预习课程,关于协议和抓包的讲解(原理和工具). 可以说基于服务器的性能一般都是基于协议的,所以我们就需要懂协议,以 ...
- django连接mysql数据库以及建表操作
django连接mysql数据库需要在project同名的目录下面的__init__.py里面加入下面的东西 import pymysql pymysql.install_as_MySQLdb() 找 ...
- 安装hyperledger fabric V1.0.0-beta
安装文档位置: https://github.com/hyperledger/fabric fabric代码托管地址 https://hyperledger-fabric.readthedoc ...