iOS Block 需不需要在Block内使用 __weak 来防止循环引用
注意本篇 讨论环境在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); }
- 上一篇: 在iOS系统上设计用户登录(原创技巧)
- 下一篇:没有了