注意本篇 讨论环境在ARC下讨论
在OC开发中使用 Block时防止循环引用,大家都知道要加 __weak 来防止循环引用,如下面的宏就是为了解决循环引用而添加的
/**
* 快速生成weak/strong类型的对象
*/
#define kWeakObject(object) __weak __typeof(object) weakObject = object;
#define kWeak(caller, object) __weak __typeof(object) caller = object;
#define kStrongObject(object) __strong __typedef(object) strongObject = object;
很多同学在时候用Block时全部加上 __weak ,其实有些时候不需要加__weak
@property(nonatomic, copy) void (^blockAction)(int, int); //对于这个block 如果在VC中使用并且在block中引用self 就要加 __weak
但当对 [UIView animations.....];//这个方法使用block就不需要加__weak
为什么是这样如何判断要不要加__weak 呢?
当block 为VC的属性时,此时 block 如果用strong属性 大家可能就很明白 VC对block进行了强引用,当时当用copy时大家可能不理解了,其实 使用copy属性,其set方法 使用copy时,在VC中也会生成一个 成员变量
BlockAction 本身就是类似函数指针 可以理解为这是个函数指针,既然 blockAction 被一个指针
编译器在为一个property合成实例变量时,也会使用所有权修饰符来修饰这个实例变量。根据property属性的不同,用来修饰实例变量的所有权修饰符也不尽相同。
ARC下
- strong
在ARC内存管理模式下,strong是一个代表对象类型的property的默认属性,并且它不能修饰用来代表简单数据类型的property。编译器在合成实例变量时,将使用__strong
修饰符。
如果另外自定义了用其他修饰符修饰的实例变量,编译器会报错。可以用这个方法来验证property的各个属性对应的实例变量的所有权修饰符。
@interface ViewController ()
{
__weak NSObject *_obj;//编译器报错:Existing instance variable '_obj' for strong property 'obj' may not be weak
}
@property (nonatomic, strong) NSObject *obj;
@end
- weak
weak也不能修饰用来代表简单数据类型的property。
编译器将为weak修饰的property生成带__weak
所有权修饰符的实例变量。
- copy ARC下
copy也不能修饰用来代表简单数据类型的property。
编译器将为copy修饰的property生成带__strong
所有权修饰符的实例变量。
编译器自动合成的setter方法会调用对象的copyWithZone:
方法。虽然第三方程序员可以自定义setter方法,但是为了程序的可读性,也应该在其中执行拷贝的逻辑。
#import "FirstViewController.h"
typedef void(^BlockAction)(int, int);
@interface FirstViewController ()
{
//这里会生成一个指针指向这个block属性
//如:NSObject *_blockAction;
// NSObject *_blockAction;
//这样写会出错
//出错原因
/*
strong
在ARC内存管理模式下,strong是一个代表对象类型的property的默认属性,并且它不能修饰用来代表简单数据类型的property。编译器在合成实例变量时,将使用__strong修饰符。
如果另外自定义了用其他修饰符修饰的实例变量,编译器会报错。可以用这个方法来验证property的各个属性对应的实例变量的所有权修饰符。
@interface ViewController ()
{
__weak NSObject *_obj;//编译器报错:Existing instance variable '_obj' for strong property 'obj' may not be weak
}
@property (nonatomic, strong) NSObject *obj;
@end
weak
weak也不能修饰用来代表简单数据类型的property。
编译器将为weak修饰的property生成带__weak所有权修饰符的实例变量。
copy
copy也不能修饰用来代表简单数据类型的property。
编译器将为copy修饰的property生成带__strong所有权修饰符的实例变量。
编译器自动合成的setter方法会调用对象的copyWithZone:方法。虽然第三方程序员可以自定义setter方法,但是为了程序的可读性,也应该在其中执行拷贝的逻辑。
*/
//报错内容 Existing instance variable '_blockAction' for strong property 'blockAction' may not be __weak
// __weak BlockAction _blockAction;
// BlockAction _blockAction;
}
//@property (nonatomic, copy) void(^blockAction)(int, int);
@property (nonatomic, copy) BlockAction blockAction;//编译器将为copy修饰的属性生成带__strong所有权修饰符的实例变量
@end
@implementation FirstViewController
- (void)viewDidLoad {
[super viewDidLoad];
//造成循环引用
_blockAction = ^(int a, int b){
NSLog(@"a+b=%d", a + b);
self.view.backgroundColor = [UIColor redColor];
};
self.view.backgroundColor = [UIColor cyanColor];
_blockAction(3, 5);
//不会循环引用
void (^block)() = ^{
self.view.backgroundColor = [UIColor yellowColor];
};
block();
}
-(void)dealloc{
NSLog(@"FirstViewController dealloc");
}
typedef void(^BlockAction)(int, int);
@interface ViewController ()
{
//这里会生成一个指针指向这个block属性
//如:NSObject *_blockAction;
// NSObject *_blockAction;
BlockAction _blockAction;
}
//@property (nonatomic, copy) void(^blockAction)(int, int);
@property (nonatomic, copy) BlockAction blockAction;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_blockAction = ^(int a, int b){
NSLog(@"a+b=%d", a + b);
};
_blockAction(3, 5);
}