Block深入浅出
- 研究工具
- clang 为了研究编译器的实现原理,我们需要使用 clang 命令。clang 命令可以将 Objetive-C 的源码改写成 C / C++ 语言的,借此可以研究 block 中各个特性的源码实现方式。
- clang -rewrite-objc main.m
- main.m中不能包含UIKit框架,命令行中解析无法识别。包含#import <Foundation/Foundation.h>是可以支持的
- C语言中变量有哪几种
- 自动变量
- 函数参数
- 静态变量
- 静态全局变量
- 全局变量

- 每种变量类型在Block中的特性及原理
- 自动变量
- 不可以修改,携带__block修饰可以被修改
- 会被Block持有(retainCount+1)
- 不带__block修饰的会被copy进Block
- 函数参数
- 可以直接修改
- 不会被Block持有(retainCount不会增加)
- 静态变量
- 可以被修改 - 由于传递给Block是内存地址值,查看Block的具体实现(查看clang后的main.cpp文件)
- 静态全局变量和全局变量
- 可以直接被访问和修改 - 由于存储区域在区全局区,由于作用区域的原因
- 不会被Block持有(retainCount不会增加)
- 自动变量
- Block中改变变量值的方式
- 传递内存地址到Block
- 指针所指向的内存不可修改,但是内存中存放的数据可以修改
- NSMutableString 变量可以直接在Block体中被appendString,但是不可以被=
- 使用__block修饰
- Block会将此标识符修饰的变量转化成一个结构体,Block体中传递并且使用的是这个结构体
- __block int i 会被转换成
struct __Block_byref_i_0 {
void *__isa; //指向自己
__Block_byref_i_0 *__forwarding; //指向自己,当被copy到堆(heap)上时,原Block此字段指向堆上的Block地址,对上的此字段仍然指向自己。这样不管__block怎么复制到堆上,还是在栈上,都可以通过(i->__forwarding->i)来访问到变量值。
int __flags;
int __size;
int i;
};
- Block捕获外部变量仅仅只捕获Block闭包里面会用到的值,其他用不到的值,它并不会去捕获。而且Block能捕获的变量只有自动变量和静态变量了。
- 传递内存地址到Block
- Block的种类
- _NSConcreteStackBlock
- 只用到外部局部变量、成员属性变量,且没有强指针引用的block都是StackBlock
- StackBlock的生命周期由系统控制的,一旦返回之后,就被系统销毁了
- 不持有对象
- 对Block的retain,release造作无效,copy造作会变成_NSConcreteMallocBlock类型
- _NSConcreteMallocBlock
- 有强指针引用或copy修饰的成员属性引用的block会被复制一份到堆中成为MallocBlock
- 没有强指针引用即销毁,生命周期由程序员控制
- 持有对象
- retain,release,copy操作生效,内存管理器中的计数会增加。(但retainCount始终为1)
- _NSConcreteGlobalBlock
- 没有用到外界变量或只用到全局变量、静态变量的block为_NSConcreteGlobalBlock
- 生命周期从创建到应用程序结束
- 不持有对象
- retain,release,copy操作为空操作
- ARC下,系统会根据下面的规则决定是否将Block复制到heap上
- _NSConcreteStackBlock
- 系统调用copy对Block复制的情况
- 手动调用copy(当Block为函数参数的时候,就需要我们手动的copy一份到堆上了。这里除去系统的API我们不需要管,比如GCD等方法中本身带usingBlock的方法)
- Block是函数的返回值
- Block被强引用(Block被赋值给__strong或者id类型)
- 调用系统API入参中含有usingBlcok的方法
- __block堆栈拷贝
- MRC 只有发生了copy,__block修饰的对象才会被copy到堆上
- ARC 发生了copy或者=(block 类型通过=进行传递时,会导致调用objc_retainBlock->_Block_copy->_Block_copy_internal方法链),__block修饰的对象才会被copy到堆上
- __block修饰的对象才会被copy到堆上 : __NSStackBlock__ 类型的 block 转换为 __NSMallocBlock__ 类型
- clang代码转换
- main.m 文件30行,大小831字节。转换后main.cpp 文件104810行,大小3.1MB。
- Block 循环引用
- 引起循环引用的条件其实很苛刻:
- Block需要被相关类(当前类或者嵌套引用的某各类)retain或copy等类似操作
- Block体中使用self(包括成员变量,成员属性等)
- 发生循环引用的拆解方式:
- 使用__weak对self进行弱引用,其实是通过弱引用的方式将闭环解开
__weak __typeof(self) wself = self;
self.myBlock = ^{
__strong __typeof(wself) self = wself;
// 使用self进行相关操作即可
};
- 使用形参的方式,将self作为参数传递给Block
- 使用__weak对self进行弱引用,其实是通过弱引用的方式将闭环解开
- 常见易混淆的场景(前提:Block没有被retain或copy的情况下,即苛刻条件中的第一条)
- GCD,系统动画等系统Block API,Block体中直接使用self不会有问题
- Block体中使用了成员属性或者成员变量,不会有问题 (参考Block种类)
- 访问了静态变量,全局变量,全局静态变量,不会引起问题
- 引起循环引用的条件其实很苛刻:
Block深入浅出的更多相关文章
- OC语言-block and delegate
参考博客 OC语言BLOCK和协议 iOS Block iOS Block循环引用精讲 iOS之轻松上手block 深入浅出Block的方方面面 Block apple官方参考 1.定义一个block ...
- 深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- [Cocoa]深入浅出Cocoa多线程编程之 block 与 dispatch quene
深入浅出 Cocoa 多线程编程之 block 与 dispatch quene 罗朝辉(http://www.cppblog.com/kesalin CC 许可,转载请注明出处 block 是 Ap ...
- 深入浅出Block的方方面面
内容大纲: 1.Blocks概要 2.Blocks模式 3.Block实质(面试常问重点) 1.Blocks概要 什么是Blocks:Blocks是C语言的扩充的功能,可以用一句话来表示Blocks的 ...
- 深入浅出-iOS Block原理和内存中位置
Posted by 微博@Yangsc_o 原创文章,版权声明:自由转载-非商用-非衍生-保持署名 | Creative Commons BY-NC-ND 3.0 #简介 今天回顾一下blcok,基本 ...
- [Machine Learning & Algorithm]CAML机器学习系列1:深入浅出ML之Regression家族
声明:本博客整理自博友@zhouyong计算广告与机器学习-技术共享平台,尊重原创,欢迎感兴趣的博友查看原文. 符号定义 这里定义<深入浅出ML>系列中涉及到的公式符号,如无特殊说明,符号 ...
- JavaScript深入浅出3-语句
慕课网教程视频地址:Javascript深入浅出 程序由语句组成,语句遵守特定语法规则 块 block {} 没有块级作用域 声明 var 异常 try catch finally 函 ...
- Block编程值得注意的那些事儿
[深入浅出Cocoa]Block编程值得注意的那些事儿 [深入浅出Cocoa]Block编程值得注意的那些事儿 罗朝辉 (http://www.cnblogs.com/kesalin/) 本文遵循 ...
- 深入浅出谈存储:如何区别NAS、SAN与DAS
深入浅出谈存储:如何区别NAS.SAN与DAS 2012年02月17日16:51 来源:新浪博客 作者:林沛满 编辑:曾智强 查看全文 赞(0)评论(1) 分享 标签: DAS , SAN , 存储系 ...
随机推荐
- 最长不下降子序列nlogn算法详解
今天花了很长时间终于弄懂了这个算法……毕竟找一个好的讲解真的太难了,所以励志我要自己写一个好的讲解QAQ 这篇文章是在懂了这个问题n^2解决方案的基础上学习. 解决的问题:给定一个序列,求最长不下降子 ...
- iOS常用动画代码
使用前 需引入QuartzCore.framework, 并在相关文件中加入 #import "QuartzCore/QuartzCore.h" 定义 shakeFeedbackO ...
- Web之真假分页
在web设计中一个无法避免的问题就是分页显示.当数据量特别大的时候,我们不可能将全部的数据都在一个页面进行显示,假设这样将严重影响到它的美观性.所以在这个时候,分页显示则成为了我们的大功臣.当然分页也 ...
- MongoDB 主从复制小实验
MongoDB 主从复制小实验 操作环境描述:WIN8 64位操作系统,内装虚拟机为CentOS 5.5 32位系统. 操作描述:跟其他关系型数据库类似,在主库进行数据操作,将数据同步到从节点,从节 ...
- hdu 3006 枚举集合能够产生的全部并集的集合
http://acm.hdu.edu.cn/showproblem.php? pid=3006 刚买的CHERRY键盘 手感真好 可惜不习惯 写代码老是打错.一个题写了一上午,都是各种按错键DEBUG ...
- StarlingMVC Framework 原理。。。
向starlingmvc 中添加bean后..会根据Metadata标签,分别交给不同的Processor去处理...然后会执行每个bean的postConstruct函数.相当于初始化函数...可以 ...
- Web开发接口测试工具——Postman插件的使用(chrome浏览器)
Postman是chrome浏览器的一款插件.Postman 可以模拟 http 请求的发送,并自动解析 JSON 和 XML 的返回数据. 可以手动的去配置各类 parameter,还支持 Basi ...
- php中常用设置
设置SESSION的生命周期 今天我所要想解决的问题,简单来说,就是设置SESSION的生命周期问题,其实问题是很简单了,只是不知道为什么,我用session_cache_expire(12*60); ...
- SkyEye的使用
转载:http://blog.csdn.net/htttw/article/details/7226754 对于希望学习ARM汇编的同学而言, 购买ARM开发板进行板上实测无疑是一个有效的方法,不过购 ...
- 1. Android 系统上一款开源的图表库
1. MPAndroidChart MPAndroidChart 是 Android 系统上一款开源的图表库.目前提供线图和饼图,支持选择.缩放和拖放. 一个可以拖动缩放的图表库,包含曲线图.直方图 ...