1、循环引用
创建一个Person类,添加一个block属性,在block内部访问peron对象:
{
Person *person = [[Person alloc] init];
person.block = ^{
NSLog(@"person = %p", person);
};
}
这段代码会导致person对象和block无法释放,原因是block捕获了person对象,内部会强引用person对象,而person对象也强引用着block,造成了相互循环引用,导致无法释放。
2、ARC环境解决block循环引用
2.1、用__weak解决(推荐)
由block内存管理可知,内部捕获的对象类型变量,引用方式会根据指向对象指针的修饰符决定,所以外部用weak修饰person,block内部也会弱引用person对象。
{
Person *person = [[Person alloc] init];
__weak typeof(person) weakPerson = person;
person.block = ^{
NSLog(@"person = %p", weakPerson);
};
}
2.2、用__block解决(不推荐)
用block修饰person对象后,在block内部就可以修改person的值,只要将内部的person指针置为nil,就可以解决循环引用,但是必须等到block执行才可以,而且置为nil后person不能再继续使用。
__block Person *person = [[Person alloc] init];
NSLog(@"1 person = %p", person);
person.block = ^{
NSLog(@"person = %p", person);
person = nil;
};
person.block();
3、MRC环境下解决block循环引用
3.1、用__unsafe_unretained解决
MRC环境下不支持weak(弱引用)的,所以可以使用unsafe_unretained解决,__unsafe_unretained不会在block内部进行retain操作。
{
Person *person = [[Person alloc] init];
__unsafe_unretained typeof(person) weakPerson = person;
person.block = ^{
NSLog(@"person = %p", person);
};
}
3.2、用__block解决
在MRC环境下block捕获的对象变量都不会retain,所以使用block修饰可以解决循环引用。
{
__block Person *person = [[Person alloc] init];
person.block = ^{
NSLog(@"person = %p", person);
};
}