Manage objective c object memory in Block
来源:互联网 发布:主机公园 php搭建 编辑:程序博客网 时间:2024/05/17 23:25
Look at the document from Apple:
When a block is copied, it creates strong references to object variables used within the block. If you use a block
within the implementation of a method:
●If you access an instance variable by reference, a strong reference is made to self;
●If you access an instance variable by value, a strong reference is made to the variable.
The following examples illustrate the two different situations:
dispatch_async(queue, ^{// instanceVariable is used by reference, a strong reference is made to selfdoSomethingWithObject(instanceVariable);});id localVariable = instanceVariable;dispatch_async(queue, ^{/*localVariable is used by value, a strong reference is made to localVariable(and not to self).Blocks and VariablesObject and Block Variables*/doSomethingWithObject(localVariable);});To override this behavior for a particular object variable, you can mark it with the __block storage type
modifier.
使用方法总结如下:(只对应NON-ARC的情况)
- 如果block没有被copy,则block中的变量在stack空间中被创建。一旦此scope执行完毕,此stack空间被释放。
- 如果block被copy,则block中的所有变量被拷贝到heap中。
此时,可以看作所有的变量都被重新拷贝了一份。
1. 对于 int, float等基本类型的变量,不需要担心release的问题,但是赋值操作将不会影响到stack空间中的变量(即block scope外的原变量)。
2. 对于objective c对象,如果直接调用self中变量,则self会被retain。由于在self中copy了这个block,会造成循环引用。
解决方法是:声明__block blockSelf = self, 在block中调用blockSelf的变量。
(注意:TestClass *blockSelf = self, blockSelf和self都指向同一个内存地址,当self先于blockSelf被释放时,blockSelf就变成了野指针!!
真的是这样吗?实际测试过,如果加上了__block,self不会先释放,会等到block执行完之后才释放。) - 如果是
id localVariable = instanceVariable;把localVariable传进block,则localVariable会被retain。
例子:
因为在copiedCompleteBlock和failure中testObject都被retain了,但是这两个block只有一个会被调用到,所以无论如何testObject都不会被释放。@ property (nonatomic, copy) RequestCompleteBlock copiedCompleteBlock;
@ property (nonatomic, copy) RequestFailureBlock failure;
TestClass *testObject = [TestClass node]; self.copiedCompleteBlock = ^(NSData *data) { [self performSelector:@selector(execute:data:) withObject:testObject afterDelay:3.0f]; }; self.failure = ^(NSError *error){ testObject.name = @"wang"; }; // set request type, HTML FWURLRequest *defaultRequest = [FWURLRequest defaultRequest]; defaultRequest.requestType = FWE_REQUESTTYPE_HTML; [defaultRequest requestWithURL:url paramsDicData:params completeBlock:self.copiedCompleteBlock failBlock:self.failure];
3. 如果声明了__block的objective c对象,可以理解成,此对象的指针地址被拷贝到了heap(其指针实际指向的地址并没有被拷贝),它指向实际地址空间的retain count并没有增加,所以读写都有效。也不需要进行额外的release。
注意,如上例子,如果
__block TestClass *testObject = [TestClass node];因为testObject不会被retain,当程序运行到当前scope外时,此testObject会被release,如果在此之后copiedCompleteBlock才被调用,则程序会崩溃。
建议:
1. 对于非self的object,不要使用__block,因为在block释放时会自动释放这些object。
2. 对于self的object,
1. 对于非self的object,不要使用__block,因为在block释放时会自动释放这些object。
2. 对于self的object,
You have a few options.1) When not using ARC, the __block qualifier on an object pointer causes it to be non-retained. Thus:__block Whatever *weakSelf = self;^{ [weakSelf ...]; }2) When using ARC on 10.7/iOS5, the __weak qualifier gets the same job done, but even better. __weak qualified variables are zeroing, so they're safer to use.3) If you're using ARC but have to support 10.6/iOS4, the __unsafe_unretained qualifier will give you a non-zeroing weak pointer.4) My MAZeroingWeakRef library provides functionality similar to __weak, but works without ARC and on older OSes. For example:MAZeroingWeakRef *weakSelfRef = [MAZeroingWeakRef refWithTarget: self];^{ [[weakSelfRef target] ...]; }Since this is a zeroing weak reference, it's safer to use than __block or __unsafe_unretained. You can get it here with a liberal license:https://github.com/mikeash/MAZeroingWeakRef
Ref:
http://lcwangchao.github.com/IOS/2012/07/16/block_retain_cycle/
http://lcwangchao.github.com/IOS/2012/07/16/block_retain_cycle/
- Manage objective c object memory in Block
- [objective-c]教程四-----内存管理(Memory Manage)
- Memory management in block
- Memory Management in Objective-C Tutorial 读后小记
- How to gzip Data in Memory Using Objective-C
- How Do I Declare A Block in Objective-C?
- How Do I Declare A Block in Objective-C?
- How Do I Declare A Block in Objective-C? [备忘]
- How Do I Declare A Block in Objective-C?
- objective-c block 讲解
- objective-c block 讲解
- objective-c block 详解
- objective-c block 讲解
- objective-c block 讲解
- Objective-C block
- objective-c block 详解
- objective-c block 详解
- Objective-C中的Block
- jdbc那点小事
- Eclipse3.7中搭建Android开发环境
- 如何通过定时关机命令,实现Windows XP的自动关机?
- linux rootfs 脚本实现 U 盘自动挂载记录
- 如何向领导汇报工作(4)
- Manage objective c object memory in Block
- RMI简单例子
- 动态初始化编号的一种方法
- poj1050 动态规划 求二维数组中子矩阵和的最大值
- hive expecting Identifier near 'table' in table name 报错
- C#中的yield return 和return有什么区别
- Eclipse swing/swt可视化开发工具windowbuilder 搭载
- RTMP协议中的AMF数据
- java中判断字符串是否为数字的三种方法