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的知识都比较隐晦,你以为你懂了,其实你没懂。需要抱着一颗不浮躁的心,慢慢的分析它的特性,写代码验证自己的想法,然后才会使用得得心应手。

 

时间: 2024-10-30 06:49:00

ARC中block块作为属性的使用笔记的相关文章

ARC下block使用情况

ARC与MRC的block有着一些区别,笔记整理ARC的block,仅仅是自己参考的笔记,详情请参考 http://www.cnbluebox.com/?p=255   在开始之前,请新建一个Model类,写几个如下的属性,用于后面测试block的特性.     Block的类型与内存管理 根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock. NSGlobalBlock:类似函数,位于text段: NSStackBlock:

block使用小结、在arc中使用block、如何防止循环引用(zz)

标签:  __block   __weak   arc   self   cfgetretaincount 分类: iOS zz from http://www.cnbluebox.com/?p=255 引言 使用block已经有一段时间了,感觉自己了解的还行,但是几天前看到CocoaChina上一个关于block的小测试主题: [小测试]你真的知道blocks在Objective-C中是怎么工作的吗?,发现竟然做错了几道, 才知道自己想当然的理解是错误的,所以抽时间学习了下,并且通过一些测试代

block(块元素)、inline(内联元素)的差别是什么?

我们首先要了解,所有的html元素,都要么是block(块元素).要么是inline(内联元素).下面了解一下block.inline各自的特点: block元素的特点: 总是在新行上开始: 高度,行高以及顶和底边距都可控制: 宽度缺省是它的容器的100%,除非设定一个宽度. inline元素的特点: 和其他元素都在一行上: 高,行高及顶和底边距不可改变: 宽度就是它的文字或图片的宽度,不可改变. 我们来详细了解它们的情况. 块元素(block element)一般是其他元素的容器元素,块元素一

iOS中Block的回调使用和解析详解_IOS

Block 回调实现 先跟着我实现最简单的 Block 回调传参的使用,如果你能举一反三,基本上可以满足了 OC 中的开发需求.已经实现的同学可以跳到下一节. 首先解释一下我们例子要实现什么功能(其实是烂大街又最形象的例子): 有两个视图控制器 A 和 B,现在点击 A 上的按钮跳转到视图 B ,并在 B 中的textfield 输入字符串,点击 B 中的跳转按钮跳转回 A ,并将之前输入的字符串 显示在 A 中的 label 上.也就是说 A 视图中需要回调 B 视图中的数据. 想不明白的同学

iOS开发中Block深入使用探索

Block在ios 4.0之后加入,并大量使用在新的ios api中.block是一个匿名的代码块,可以作为传递给其他对象的参数,并得到返回值.从本质上讲,block同其他普通的变量类似,只是其储存的数据是一个函数体.Block不只是针对Objective-C的专利,而是一种可以应用于C.C++和OBjective-C的语言层面的新特性.通过使用block,开发者可以将一段代码段像某一个数值一样当做参数传递给函数.同时,blocks也是Objective-C的一种对象,可以像其他对象一样添加到N

Ruby中的块的知识

  这篇文章主要介绍了详解Ruby中的块的知识,包括yield语句和begin/end块等知识点,需要的朋友可以参考下 语法: ? 1 2 3 4 5 block_name{ statement1 statement2 .......... } 在这里,将学习如何通过使用一个简单的 yield 语句调用块.还将学习使用yield语句具有参数调用块.将检查的示例代码,这两种类型的 yield 语句. yield 语句: 让我们来看看在yield语句的一个例子: ? 1 2 3 4 5 6 7 8

举例说明Java中代码块的执行顺序_java

前言    今天在看Android ContentProvider实现的时候,突然想到了Java类在new的过程中,静态域.静态块.非静态域.非静态块.构造函数的执行顺序问题.其实这是一个很经典的问题,非常考察对Java基础知识的掌握程度.很多面试过程中相信也有这样的问题,趁着周末有时间复习一下. 结论    这里先把整理好的结论抛给大家,然后我在写个程序来验证我们的结论.在Java类被new的过程中,执行顺序如下:     实现自身的静态属性和静态代码块.(根据代码出现的顺序决定谁先执行)  

ios-使用 ARC 中copy的困惑

问题描述 使用 ARC 中copy的困惑 在使用ARC时有一个NSString属性,需要@property(nonatomic, copy).但是当我将我的工程转成ARC后,在初始化方法中依旧存在: _someString = [someStringParameter copy] 这是bug吗?还是在ARC中还是需要指出copy.需不需要这样: self.someString = someStringParameter 请明白人指点,谢谢 解决方案 首先,这不是bug 其次,还是需要明确说明co

IOS 中block结构的简单用法

自从block出现之后,很多API都开始采用这样的结构,由此可见,block确实有许多优势存在,这里将一些简单用法总结如下: 一.如何声明一个block变量 我们通过^符号来声明block类型,形式如下: void (^myBlock)(); 其中第一个void是返回值,可以是任意类型,中间括号中^后面的是这个block变量的名字,我把它命名为myBlock,最后一个括号中是参数,如果多参数,可以写成如下样式: int (^myBlock)(int,int); 同样,你也可以给参数起名字: in