经常听说block的循环应用,就是说的A引用B ,B又引用A,这样的交叉引用,导致AB都不能释放,后果就是,内存会增加,甚至导致程序崩溃。
下面通过代码来看产生的原因
首先定义一个Friend的类
1.1 Friend.h文件
import <Foundation/Foundation.h>
@interface Friend : NSObject
@property(nonatomic ,copy) void(^testBlock)();
-(void)run;
@end
1.2 Friend.m文件
import "Friend.h"
@implementation Friend
添加了一个run的测试的方法
-(void)run {
NSLog(@" person run");
}
-(void)dealloc{
NSLog(@"friend被释放了");
}
2.0 在viecontroller.m文件中
-
(void)viewDidLoad {
[super viewDidLoad];Friend *p = [[Friend alloc]init];
p.testBlock =^{
这个时候系统就会产生警告,产生了循环引用
[ p run];
};
}
3 下面来讨论产生循环引用的原因
3.1
Friend p = [[Friend alloc]init]; 这句代码的解释是
当实例化一个对象的时候 这个对象的p 指针放在栈内存中,
对象p存放在堆内存中。
3.2 @property(nonatomic ,copy) void(^testBlock)();
当我们声明一个block的成员变量的时候,这个block成员变量存放在栈中,
但我们调用这个block用的的是copy属性 (如果没有对block用copy,block存放 在栈内存控件中),这个block就会转移到堆中,这样就会对在block中的对象产生强引用。 那么执行这句代码的时候。堆空间中的block会指向在p这个对象中用的block,这样block就会对对象p产生一个强引用,但是testblock 也是P的成员属性。 所以循环引用就产生了。
p.testBlock =^{
[ p run];
};
二 Block中的循环应用的处理方法
-
(void)viewDidLoad {
[super viewDidLoad];Friend *p = [[Friend alloc]init];
下面这两句代码任选一句就可以了,但是官方推荐选用第一句__weak typeof (p) weakp = p;
__unsafe_unretained typeof (p) weaka = p ;
p.testBlock =^{
[weakp run];
};
}