@interface A_ViewController ()
typedef void(^demoBlock)(NSString *name);
{
NSString *name; // 表示实例变量
}
@property (nonatomic, copy) demoBlock tBlock; // 表示属性
@property (nonatomic, strong) NSString *str;
@end
1、当block不是self的属性或者实例变量时,不会导致强引用
@implementation A_ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
[self getNewName:^(NSString *name) {
_str = name; // 此处不会导致循环引用,虽self引用计数+1,block函数执行完后,block函数被释放,则self引用计数-1
}];
}
- (void)getNewName:(demoBlock)block {
NSString *name = @"刘德华";
block(name);
}
- (void)dealloc {
NSLog(@"%@", myName);
NSLog(@"A_ViewController");
}
2、当block是self的属性或者实例变量时,会导致强引用
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
self.tBlock = ^(NSString *name) {
myName = name; // 此时会导致循环引用,tBlock 对self引用计数+1,tBlock执行完后,由于tBlock是self的属性还没释放。会导致tBlock等待self销毁,self等待tBlock销毁。互相持有,内存不能释放
};
}
- (void)getNewName:(demoBlock)block {
NSString *name = @"刘德华";
block(name);
}
3、小贴士:
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
// __weak typeof(self) weakself = self; //weakself是一个临时变量,在
self.tBlock = ^(NSString *name) {
myName = name;
self.str = name; // 此处会有警告:Capturing 'self' strongly in this block is likely to lead to a retain cycle
_str = name; // 而这样写没有
};
}
原因是_str是@property修饰str时,系统自动给str生成了实例变量名_str和相应的get和set方法。
只有tBlock里面出现self这样的字眼时,编译器才会给警告,在开发时要特别注意实例变量在self
持有的block里调用,需要用weakself修饰。
__weak typeof(self) weakself = self;
4、strongSelf的使用场景---设置block延时5秒钟再执行,
状态一:weakself修饰 5秒钟内pop出控制器 先执行dealloc再执行block,打印内容(null), (null)。
状态二:strongself修饰 5秒钟内pop出控制器 先执行block再执行dealloc,打印内容<A_ViewController: 0x7fb834e0cd80>, 程鹏。
实际场景:在执行网络请求的时候,未执行block回调方法时
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor orangeColor];
self.str = @"张学友";
__weak typeof(self) weakself = self;
self.tBlock = ^{
// __strong typeof(self) strongself = weakself;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakself.str = @"程鹏";
NSLog(@"%@, %@", weakself, weakself.str);
});
};
self.tBlock();
}
- (void)dealloc {
NSLog(@"%@", self.str);
NSLog(@"A_ViewController");
}
5、自定义视图 viewA 包含一个block属性
viewA被添加到viewController上,viewA的属性block会导致循环引用问题,使用时注意。
注意循环引用问题,self持有agreeView,agreeView持有agreeBlock
# 此处block内不需要进行网络请求或者延时操作,在self被释放前,block一定会执行完成,所以不需要考虑使用StrongSelf的用法
// GDPR个人隐私声明视图
HNAgreePrivacyView *agreeView = [[HNAgreePrivacyView alloc] init];
[self.view addSubview:agreeView];
[agreeView mas_makeConstraints:^(HMTMASConstraintMaker *make) {
make.top.mas_equalTo(phoneTextField.mas_bottom).offset(HOMENETWORK_CUSTOM_DISTANCE*2);
make.leading.mas_equalTo(self.view).offset(HOMENETWORK_CUSTOM_DISTANCE);
make.trailing.mas_equalTo(self.view).offset(-HOMENETWORK_CUSTOM_DISTANCE);
make.height.mas_equalTo(agreeButtonWH);
}];
# 注意循环引用问题,self持有agreeView,agreeView持有agreeBlock
# 此处block内不需要进行网络请求或者延时操作,在self被释放前,block一定会执行完成
# 所以不需要考虑使用StrongSelf的用法
agreeView.agreeBlock = ^(BOOL isSelected) {
};
// 点击查看隐私文件
agreeView.checkBlock = ^{
};