iOS内存管理--Block属性用copy修饰 & 避免循环引用的问题

Posted zzz098zzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了iOS内存管理--Block属性用copy修饰 & 避免循环引用的问题相关的知识,希望对你有一定的参考价值。

一、Block的类型

根据Block在内存中的位置分为三种类型NSGlobalBlockNSStackBlock, NSMallocBlock

  • NSGlobalBlock:类似函数,位于text段;
  • NSStackBlock:位于栈内存,函数返回后Block将无效;
  • NSMallocBlock:位于堆内存。


二、Blockcopyretainrelease操作

  不同于NSObjeccopyretainrelease操作:

  • Block_copycopy等效,Block_releaserelease等效;
  • Block不管是retaincopyrelease都不会改变引用计数retainCountretainCount终是1
  • NSGlobalBlockretaincopyrelease操作都无效;
  • NSStackBlockretainrelease操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的错误是[[mutableAarry addObject:stackBlock],(补:在arc中不用担心此问题,因为arc中会默认将实例化的block贝到堆上在函数出栈后,从mutableArray中取到的stackBlock经被回收,变成了野指针。正确的做法是先将stackBlock copy到堆上,然后加入数组:[mutableArray addObject:[[stackBlock copy] autorelease]]支持copycopy之后生成新的NSMallocBlock类型对象
  • NSMallocBlock:支持retainrelease,虽然retainCount终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain
  • 尽量不要Block使用retain操作

三、ARC与非ARC下的block

对于引用了外部变量的Block,如果没有对他进行copy,他的作用域只会在声明他的函数栈内(类型是__NSStackBlock__),如果想在非ARC下直接返回此类Block,Xcode会提示编译错误的,如下图:

屏幕快照 2013-12-13 下午5.15.13

(Xcode提示Returning block that lives on the local stack)

而在ARC环境下,上述代码会编译通过,因为ARC会自动加入copy操作。

比如可以在ARC下运行如下代码:

//ARC
MyBlock block = func();
NSLog(@"%d", block());
NSLog(@"%@", [block class]);

输出:

123
__NSMallocBlock__

以上是关于iOS内存管理--Block属性用copy修饰 & 避免循环引用的问题的主要内容,如果未能解决你的问题,请参考以下文章

iOS block 为啥官方文档建议用 copy 修饰

iOS中为什么block用copy属性

iOS开发之Block

iOS内存管理--NSArray与NSMutableArray用copy修饰还是strong

iOS内存管理--NSArray与NSMutableArray用copy修饰还是strong

block要用copy修饰,还是用strong