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原理的更多相关文章

  1. 转:Block原理及引用循环问题

    2010年WWDC发布iOS4时Apple对Objective-C进行了一次重要的升级:支持Block.说到底这东西就是闭包,其他高级语音例如Java和C++已有支持,第一次使用Block感觉满简单好 ...

  2. 深入浅出-iOS Block原理和内存中位置

    Posted by 微博@Yangsc_o 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 #简介 今天回顾一下blcok,基本 ...

  3. iOS之Block总结以及内存管理

    block定义 struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(v ...

  4. iOS之block,一点小心得

    作为一个iOS开发程序员,没用过block是不可能的.这次我探讨的是block原理,但是有些更深层次的东西,我也不是很清楚,以后随着更加了解block将会慢慢完善. 第一个问题,什么是block? 我 ...

  5. block注意事项

    1.block的声明和注意事项 #import "ZYViewController.h" @interface ZYViewController () @end /*用typede ...

  6. fir.im Weekly - 一切从知识重构开始

    一年之计在于春,大自然开始了新元素的重构.你的知识库是否也该重构更新呢? 本期 fir.im Weekly 包含最新的Android.iOS 开发工具.源码和好玩的UI 动画分享,希望对你有用. Sw ...

  7. POJ 1523 (割点+连通分量)

    题目链接:http://poj.org/problem?id=1523 题目大意:连通图,找图中割点,并计算切除该割点后,图中的连通分量个数. 解题思路: POJ的数据很弱. Tarjan法求割点. ...

  8. MyQQ 前言

    从接触IOS以来也将近8个月了,学习了不少知识. 看了一系列的书籍如: <objective-c 开发入门>--语法介绍,学习一门语言是开发的基础.所以这是我大致对语法语句学习的锻炼地方, ...

  9. ARC下需要注意的内存管理

    ARC下需要注意的内存管理 2016/04/03 · iOS开发 · 内存管理 分享到:1 原文出处: 一不(@luoyibu)    之前发了一篇关于图片加载优化的文章,还是引起很多人关注的,不过也 ...

随机推荐

  1. 计时器setTimeout()

    setTimeout()计时器,在载入后延迟指定时间后,去执行一次表达式,仅执行一次. 语法: setTimeout(代码,延迟时间); 参数说明: 1. 要调用的函数或要执行的代码串. 2. 延时时 ...

  2. jquery.autocomplete 搜索文字提示

    function GetJobTitle(obj) { $(obj).autocomplete("GetJobTitle.ashx", { max: 12, //列表里的条目数 m ...

  3. [UE4]Tool Tip - 提示信息

    一.每一个Widget都有Tool Tip,在运行时鼠标移动到UI上,就会显示填写的Tool Tip文字   二.Toop Tips的字体样式和大小不可更改.但是可以Tool Tip可以绑定到一个Wi ...

  4. [UE4]枚举Enum和Switch Enum

  5. [UE4]获得特定类型的所有Actor:Get All Actors Of Class、Get All Actors with Interface、Get All Actors with Tag

  6. Laravel 5.5 FormRequest 自定义错误消息 postman调试时X-Requested-With设为XMLHttpRequest

    Laravel 5.5 FormRequest 自定义错误消息 使用FormRequest进行表单验证,就不用让验证逻辑和控制器里面的逻辑都混在一起.但在使用的时候呢,发现json错误返回的数据,与我 ...

  7. 20165312 C语言基础调查和JAVA学习展望

    C语言基础调查和JAVA学习展望 一.有关学习技能的经历 掌握一项技能,我认为最重要的是练习和认真程度. 我在上幼儿园的时候学过电子琴,上台表演过多次,但是三四年之后就半途而废了,后来小学毕业之后对钢 ...

  8. 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 ...

  9. Java 1.ExecutorService四种线程池的例子与说明

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  10. Web Service进阶

    选框架犹如选媳妇,选来选去,最后我还是选了“丑媳妇(CXF)”,为什么是它?因为 CXF 是 Apache 旗下的一款非常优秀的 WS 开源框架,具备轻量级的特性,而且能无缝整合到 Spring 中. ...