何时用strongSelf和weakSelf

@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,打印内容, 程鹏。
实际场景:在执行网络请求的时候,未执行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 = ^{
        
    };

你可能感兴趣的:(何时用strongSelf和weakSelf)