HR's Blog

Swimming 🏊 in the sea🌊of code!

0%

weakSelf 和 strongSelf.

.

weakSelf是用来解决循环引用
strongSelf则是保证任何情况下self在超出作用域以后仍旧能够使用。

示例

定义个自定义的类HRViewController。通过touchesBegan:跳转到这个Controller,在HRViewController里面的``touchesBegan:来实现退出HRViewController控制器。通过进入和退出HRViewController`来查看效果。

前置条件

1
2
3
4
5
6
7
8
@interface HRViewController ()
@property (copy, nonatomic) void(^test)();
@property (nonatomic, copy) NSString *locationInfo;
@end

-(void)dealloc {
NSLog(@"HRViewController销毁");
}

WeakSelf

1
2
3
4
5
6
7
8
9
10
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.locationInfo = @"北京";
self.test = ^{
NSLog(@"地址:%@", self.locationInfo);
};
self.test();
self.view.backgroundColor = UIColor.redColor;
}

上面的代码会导致死循环,HRViewController销毁不会被打印。Controller拥有这个Block,这个Bock强引用Controller,所以不会被销毁。如下面代码,block中改为弱引用,问题解决,HRViewController销毁打印。

1
2
3
4
5
6
7
8
9
10
11
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.locationInfo = @"北京";
__weak HRViewController *weakSelf = self;
self.test = ^{
NSLog(@"地址:%@", weakSelf.locationInfo);
};
self.test();
self.view.backgroundColor = UIColor.redColor;
}

StrongSelf

1
2
3
4
5
6
7
8
9
10
__weak HRViewController *weakSelf = self;
self.test = ^{
NSLog(@"地址:%@", weakSelf.locationInfo);
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"执行延时");
strongSelf.locationInfo = @"湖南";
NSLog(@"地址:%@", weakSelf.locationInfo);
});
};
self.test();

进入Controller以后,在5秒内退出这个Controller。执行到延时block里面的代码的时候,Controller已经销毁了,locationInfo也随之销毁了,所以湖南不能被赋值,里面的打印地址为null

1
2
3
4
地址:北京
HRViewController销毁
执行延时
地址:(null)

这时候我们就要用到strongSelf来延迟Controller的销毁。

1
2
3
4
5
6
7
8
9
10
11
__weak HRViewController *weakSelf = self;
self.test = ^{
NSLog(@"地址:%@", weakSelf.locationInfo);
__strong HRViewController *strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"执行延时");
strongSelf.locationInfo = @"湖南";
NSLog(@"地址:%@", strongSelf.locationInfo);
});
};
self.test();

从打印可以看出Controller最终在赋值完以后才销毁,所以达到了延迟Controller的销毁的目的。

1
2
3
4
地址:北京
执行延时
地址:湖南
HRViewController销毁

不能直接在延迟block里面使用self,这样又是会死循环。

相关链接

https://stackoverflow.com/questions/11013587/differences-between-strong-and-weak-in-
https://blog.csdn.net/u013046795/article/details/50789442