我们都知道,在使用block的时候需要特别注意循环使用问题,比如在一个ClassA中:
@interface DDDViewController ()
@property (nonatomic, copy) void(^block)();
@property (nonatomic, strong) NSString *dog;
@end
@implementation DDDViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.dog = @"222";
self.block = ^(){
NSLog(@"%@",self.dog);
};
self.block();
}
-(void)dealloc
{
NSLog(@"dealloc");
}
-
上面这中情况下,就有循环问题发生,因为block本身是self的一个属性,self对block持有;而block会对它内部的变量进行持有,此时它内部就有self这个变量;导致的结果就是self和block互相持有,形成一个闭环;
-
解决的方法,当然很简单,比如这样:
@interface DDDViewController ()
@property (nonatomic, copy) void(^block)();
@property (nonatomic, strong) NSString *dog;
@end
@implementation DDDViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.dog = @"222";
__weak DDDViewController *weak = self;
self.block = ^(){
NSLog(@"====%@",weak.dog);
};
self.block();
}
-(void)dealloc
{
NSLog(@"dealloc");
}
使用weak修饰即可打破刚才的闭环。但是,比如有个这样的情景:
当前这个DDDViewController是被ClassA给Push出来的,然后执行下面的代码:
@interface DDDViewController ()
@property (nonatomic, copy) void(^block)();
@property (nonatomic, strong) NSString *dog;
@end
@implementation DDDViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.dog = @"222";
__weak DDDViewController *weak = self;
self.block = ^(){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"====%@",weak.dog);
});
};
self.block();
}
-(void)dealloc
{
NSLog(@"dealloc");
}
大家认为打印是什么结果?
- 其实有两种打印结果,分别是
- 第一中结果是进去该界面后,在5s内退出
2016-12-07 10:22:00.444 CeShi[1180:47515] dealloc
2016-12-07 10:22:03.491 CeShi[1180:47515] ====(null)
- 第二种结果是进去该界面后,在5s后退出
2016-12-07 10:22:12.285 CeShi[1180:47515] ====222
2016-12-07 10:22:14.161 CeShi[1180:47515] dealloc
- 显然我们是希望看到结果2的,但是因为Vc被提前释放了,导致它的属性也被提前释放,然后我们去打印的时候,就是现实的null了,这个问题怎么解决?代码如下:
@interface DDDViewController ()
@property (nonatomic, copy) void(^block)();
@property (nonatomic, strong) NSString *dog;
@end
@implementation DDDViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
self.dog = @"222";
__weak DDDViewController *weak = self;
self.block = ^(){
__strong typeof(self) strongSelf = weak;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"====%@",strongSelf.dog);
});
};
self.block();
}
-(void)dealloc
{
NSLog(@"dealloc");
}
- 这样做,打印结果只有一种,即结果2。
所以我们平常写block的时候,并且需要在block中用到self的时候,可以采取这种方式
- 思考:什么时候在block中用self,但是不需要修饰?
比如这个:
[UIView animateWithDuration:0.2 animations:^{
self.alpha = 1;
}];
- 答案看到代码的时候就挺简单了:即block本身并不被self所持有,而是被别的对象所持有,此时block内使用self,就不需要被修饰
网友评论