ARC中block块作为属性的使用笔记
ARC中block块作为属性的使用笔记

block较难理解,根据在内存中的分布情况就分为3种类型,根据使用的情形又分为很多很多种。虽然用起来容易,但使用不当会造成内存泄露,虽然都是这么说,但你真的研究过为什么会泄露吗?为什么有些时候外部变量进入block的时候会导致引用计数+1呢?
本人做过MRC以及ARC的开发,但大势所趋,ARC将是以后开发的主要模式,即使有MRC也是ARC混编MRC的代码,所以,本文的block的一些使用上的心得都基于ARC的,已经不考虑MRC的了,请看官注意,MRC与ARC的block是有着很多很多区别的。
注意,以下心得是我自己长时间收集资料以及自己验证所的出来的一些技巧与结论,不代表它的正确性,这仅仅是笔记,取舍由你决定,最好自己验证一下。
首先建立出如下形式的工程,CV1 push 到CV2的这种形式。

它们的强引用关系如下:

以下是CV2的代码,注意,要将block定义成copy属性。

block被copy了有着什么现象发生呢?引用一段原文。
http://stackoverflow.com/questions/16149653/what-is-the-role-of-the-copy-in-the-arc
Blocks are similar to other objects for memory management, but not the same. When a block which accesses local variables is created, it is created on the stack. This means that it is only valid as long as its scope exists. To save this block for later, you must copy it, which copies it to the heap.
Blocks与其他对象的内存管理相似,但又有着不同。当一个block(block当中有着外部变量进入)被创建了,它是在堆区中的。那意味着,当block中的代码执行完毕之后,这段代码就再也不合法了,会被清除掉。为了让这个block存活时间更久。你必须copy,将它拷贝到栈区。
1. CV1 push 到CV2,CV2在栈区里面,CV2 pop 掉后整个控制器都被释放。
2. 作为属性的block被copy之后会出现在CV2栈区里面,为什么在栈区里面,很简单,它要随着CV2的生命周期一致,CV2 pop 掉后这个block也会跟着一起消失的。
他们的强引用关系如下图所示:

以下情形叫做有外部变量进入block的情形,其中的self.name就是控制器CV2的一个属性,对于block来讲属于外部变量。

这里有一个问题,对于进入到block里面的外部变量,为什么会被block强引用呢?
我们可以这么想,block块中的代码并不是马上就会执行的,需要你手动调用才行,如上例中的self.oneBlock(@“YouXianMing”);有时候,这个方法都执行结束了,这个block还没有执行,如果block中的对象没有被block强引用,很有可能那个变量已经消失了却还调用了block,直接后果就是崩溃。为了保证block至少能用上一次,它必须强引用进入到里面的外部变量。
所以上图中的强引用关系图如下所示:

如果CV2 pop 了,其释放过程是这样子的:

CV2被CV1强引用消失,CV2就会挨个检查强引用,如果没有发现自己被什么强引用,就会把所有的内容清除掉,就是上图中的oneBlock以及name。
最后,之后轮到oneBlock了,它也会解除name的强引用关系:

至此,都是很完美的,没有内存泄露什么的。
我们把代码修改成如下的形式,我们在block中执行一个方法,让控制器执行一个方法,即[self ......];

它们的强引用关系图如下,注意下图中的蓝色的线条,因为外部变量self(CV2自身)传了进来,只出现的self也算传进来了哦。

这个时候,你如果将 CV2 pop掉。它们的关系图如下所示:

这个时候,CV2会检测自己有没有被强引用,结果发现被一个对象oneBlock强引用了,那么它自身就不会被释放掉,整个CV2都泄露了呢,泄露的原因就是循环引用。
这时候,你再从CV1 push 出CV2,以下是关系图:

再次pop又会泄露一个CV2。每次的push与pop都会导致一个新的CV2整体被泄露哦。
这还只是作为属性的block。其他的还没讲呢。作为属性的block是最容易出现循环引用事件的。block的知识都比较隐晦,你以为你懂了,其实你没懂。需要抱着一颗不浮躁的心,慢慢的分析它的特性,写代码验证自己的想法,然后才会使用得得心应手。
ARC中block块作为属性的使用笔记的更多相关文章
- ARC下block使用情况
ARC与MRC的block有着一些区别,笔记整理ARC的block,仅仅是自己参考的笔记,详情请参考 http://www.cnbluebox.com/?p=255 在开始之前,请新建一个Model类 ...
- Block块
block的标志:^ 特点: 1.可以保存代码 2.有返回值 3.有形参 4.调用方式和c语言一样 5.可以访问外部变量,但不能修改变量的值:如果使用__block关键字修饰的变量才可以. 1)创建 ...
- iOS中为什么block用copy属性
1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...
- block使用小结、在arc中使用block、如何防止循环引用
引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗 ...
- html中的块元素(Block)和内联元素(Inline)(转)
我们首先要了解,所有的html元素,都要么是块元素(block).要么是内联元素(inline).下面了解一下块元素.内联元素各自的特点: 块元素(block)的特点: 1.总是在新行上开始:2.高度 ...
- iOS开发——高级篇——iOS中为什么block用copy属性
1. Block的声明和线程安全Block属性的声明,首先需要用copy修饰符,因为只有copy后的Block才会在堆中,栈中的Block的生命周期是和栈绑定的,可以参考之前的文章(iOS: 非ARC ...
- Objective-C中的block块语法
#import <Foundation/Foundation.h> /* OC不同于Java C++ 它没有字符串对象 只有NS对象 NS就是乔布斯第一个公司NeXt的类集合 被收购之后才 ...
- 关于block块使用的6点注意事项
对于刚学习OC新伙伴,block块一直都是一个比较纠结.比较难懂的知识点,不过,在使用一段时间后,就会感觉很酸爽.block块的原理及使用我就不再赘述,网上有很多这方面的资料.我个人使用这么长时间以来 ...
- iOS中Block的用法,举例,解析与底层原理(这可能是最详细的Block解析)
1. 前言 Block:带有自动变量(局部变量)的匿名函数.它是C语言的扩充功能.之所以是拓展,是因为C语言不允许存在这样匿名函数. 1.1 匿名函数 匿名函数是指不带函数名称函数.C语言中,函数是怎 ...
随机推荐
- dos命令行运行.class源文件错误解决办法
dos命令行运行java源文件 public static void main(String[] args) throws IOException { // TODO Auto-generated m ...
- java-双大括号实例初始化的反模式
今天在看springboot的batch时, 看到这样一段代码, 直接把我看懵了, 于是找了一下, 发现这 两个大括号 {{ 叫实例初始化器 FlatFileItemReader<Person ...
- 反转ListBox的ListBoxItem(控件级别,不是数据的反转)
在默认的排序下,当将ListBoxItem往下移动时,ListBoxItem是从其他ListBoxItem的底部移动的如下图: 但当往上移动时,情况则不是如此, 所以需要尝试对ListBo ...
- Inno Setup设置在安装Finished页面,点击finish后打开网页
在安装的最后一个页面FinishPage中点击Finished然后打开一个网页 这个功能貌似很简单,不就是在点击finish按钮给它绑定事件,问题立马解决. 在普通的桌面应用程序开发中的确是这样做的, ...
- AngularJS 的常用特性(五)
13.使用路由和 $location 切换视图 对于一些单页面应用来说,有时候需要为用户展示或者隐藏一些子页面视图,可以利用 Angular 的 $route 服务来管理这种场景. 你可以利用路由服务 ...
- Major GC和Full GC的区别是什么?触发条件呢?
作者:RednaxelaFX链接:http://www.zhihu.com/question/41922036/answer/93079526来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非 ...
- C语言——<计算>_较大两个数相乘
例题:9876543210*1234567890 的乘积 分析:正常的数据结构已经无法满足这么大的数相乘的结果.只能使用数组来进行操作. 1.两个数都用字符数组来接收. 2.接收后,因为每一位要乘以另 ...
- [BZOJ 5074]小B的数字
Description 题库链接 给你一个长度为 \(n\) 的序列 \(a_1,a_2,\cdots,a_n\) ,让你生成另一个序列 \(b_1,b_2,\cdots,b_n\) ,使得 \(\f ...
- c#基础学习(0724)之可变参数、ref和out
params可变参数,无论有几个参数,必须出现在参数列表的最后,可以为可变参数直接传递一个对应类型的数组 #region 可变参数 //1.如果方法有多个参数,可变参数可以作为最后一个参数 //2.可 ...
- 基础拾遗----RabbitMQ
基础拾遗 基础拾遗------特性详解 基础拾遗------webservice详解 基础拾遗------redis详解 基础拾遗------反射详解 基础拾遗------委托详解 基础拾遗----- ...