ARC下block使用情况
ARC与MRC的block有着一些区别,笔记整理ARC的block,仅仅是自己参考的笔记,详情请参考 http://www.cnbluebox.com/?p=255
在开始之前,请新建一个Model类,写几个如下的属性,用于后面测试block的特性.
Block的类型与内存管理
根据Block在内存中的位置分为三种类型NSGlobalBlock,NSStackBlock, NSMallocBlock。
- NSGlobalBlock:类似函数,位于text段;
- NSStackBlock:位于栈内存,函数返回后Block将无效;
- NSMallocBlock:位于堆内存。
从打印信息处可以看出,该block是一个__NSGlobalBlock__.
虽然只是简单的改了一下,但很明显,刚刚的__NSGlobalBlock__已经变成了__NSMallocBlock__,此处我们可以得知,在处理对象时,block会malloc的.
我们使用弱引用集合NSHashTable来验证,一个block的强引用的情况.
#import <Foundation/Foundation.h> @interface YX_NSHashTable : NSObject + (void)add:(id)obj; + (BOOL)contain:(id)obj; + (NSArray *)allObjs; @end
#import "YX_NSHashTable.h" static NSHashTable *table = nil; @implementation YX_NSHashTable + (void)initialize { if (self == [YX_NSHashTable class]) { table = [NSHashTable weakObjectsHashTable]; } } + (void)add:(id)obj { [table addObject:obj]; } + (BOOL)contain:(id)obj { return [table containsObject:obj]; } + (NSArray *)allObjs { return [table allObjects]; } @end
从打印信息还看不出什么东西出来-_-!!
将block设置成copy属性后,很明显,还没运行就已经提示了循环引用的问题.
控制器强引用了一个block,而该malloc的block也强引用了控制器.所以,导致了循环引用的问题.
堆内存的一个明显的特性就是:他会强引用block中的对象,如果该block被其他不会被释放的东西给强引用了,就会导致循环引用.
问:ARC支持dispatch_queue吗?
http://stackoverflow.com/questions/8618632/does-arc-support-dispatch-queues/8619055#8619055
If your deployment target is lower than iOS 6.0 or Mac OS X 10.8
You need to use dispatch_retain
and
dispatch_release
on your queue. ARC does not manage them.
If your deployment target is iOS 6.0 or Mac OS X 10.8 or later
ARC will manage your queue for you. You do not need to (and cannot) use
dispatch_retain
or dispatch_release
if ARC is
enabled.
结论:如果你的iOS编译的target是iOS6.0+,ARC支持dispatch_queue.
问:如何才能在block中不至于造成泄露呢?
即使是NSMallocBlock也不一定会泄露,但是如果是一个copy属性的block,它一定是NSMallocBlock,这个就需要十分注意.出现在这个block中的对象,是会被这个包含这个block的对象给强引用的.如果这个对象是个单例而不会被释放掉,那就泄露了.
问:这种block会导致_model对象泄露吗?
因为block里面出现了对象,这个block变成了NSMallocBlock,理论上,_model会在该block的生命周期中一直被持有.直到它被销毁.
问:方法中的block是怎么回事呢?
方法中的block是栈block,不用担心会被强引用.