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) 之前发了一篇关于图片加载优化的文章,还是引起很多人关注的,不过也 ...
随机推荐
- Linux下自制回收站
Linux下自制回收站 相信熟悉linux系统的人都知道rm的厉害,也大都听说过有rm造成的生产事故,本文将详细介绍如何在linux环境下制作回收站以避免数据误删除,如何恢复回收站中的数据,如何查看回 ...
- [UE4]游戏主循环
游戏的运行模型 理解游戏的运行模型,对处理很多游戏错误有非常大的帮助. 游戏是有一个主循环的.那么游戏主循环做了什么事情呢? 游戏主循环一次就表示一帧,游戏主循环包括:接受输入.处理游戏逻辑.渲染.S ...
- [UE4]修改相机裁剪距离
在UE4中,相机距离一个物体太近,物体就会被裁剪,这个距离是一个全局设定,无法单个相机设置. 项目设置:
- SpringMVC 源码分析
一个东西用久了,自然就会从仅使用的层面上升到探究其原理的层面,在javaweb中springmvc更是如此,越是优秀的框架,其底层实现代码更是复杂,而在我看来,一个优秀程序猿就相当于一名武林高手,不断 ...
- Android中Handler.removeCallbacksAndMessages(null)的作用
众所周知,在Android开发中会大量使用到Handler.但是,由于与activity生命周期不一致,当一个Activity被销毁时,如果Handler对象有Message在排队,则无法释放,进而导 ...
- 基于pyQt5开发的股价显示器(原创)
#/usr/bin/env python # -*- coding: utf-8 -*- ''' @author="livermorium116" 为了绕开公司内网而开发的 股票实 ...
- 关于python中生成器之Send方法
#send主要是用于外部与生成器对象的交互def func1(): # 生成器函数 print("ok1") x = 10 # 函数内局部变量x赋值为10 print(x) x = ...
- 性能测试day02_预习知识
在进入第二天的学习之前,我想我们需要提前先了解一下基础的知识,所以这一篇主要讲解的就是预习课程,关于协议和抓包的讲解(原理和工具). 可以说基于服务器的性能一般都是基于协议的,所以我们就需要懂协议,以 ...
- redis下操作String
redis操作string string是redis最基本的类型 最大能存储512MB数据 string类型是二进制安全的,即可以为任何数据,比如数字.图片.序列化对象等 基本命令 设置 设置键值 s ...
- [配置]给Myeclipse配置Tomcat
http://jingyan.baidu.com/article/4853e1e53465271909f72690.html 步骤 1 2 3 4 5 6 7 8 Meclipse是java We ...