Block从入门到放弃宝典(二):循环引用
2016-10-11 本文已影响552人
键盘风筝
十一大家去哪happy了,不过去哪都是开启看人模式,这是block的第二篇文章,给大家简单剖析一些循环引用的问题,大家下一篇想看什么可以给楼主留言或私信,都会满足大家的
其实block是个双面剑,用好了可以使代码更简洁,增加可读性,但是往往大家忽略了循环引用的问题,所以还是希望大家要知其一,更要知其二,本着实用性为主,还是从实际项目中给大家介绍几个经典的循环引用场景.
怎么造成循环引用
两个对象相互持有,谁也不释放谁,就造成循环应用了
循环引用.jpeg循环引用场景(一)
typedef void(^block)();
@interface ViewController ()
@property (copy, nonatomic) block testBlock;
@property (copy, nonatomic) NSString *testString;
- (void)viewDidLoad {
[super viewDidLoad];
self. testBlock = ^(){
NSString *str = self.blockString;
};
}
如何造成循环引用
这样会造成循环引用,因为self.testBlock和self.blockString互相都是强引用,导致互相都不释放,我画出两者的关系
循环引用场景一.png
解决方法
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self. testBlock = ^(){
NSString *str = weakSelf.blockString;
};
}
原理:使用__weak来修饰self对象,使其在block中不被持有,破坏循环引用
打破循环引用.png
循环引用场景(二)
大家在使用网络请求的时候,经常会用到block,但是殊不知也有可能已经循环引用了
首先创建一个NetWorkTool,并写一个方法
@interface NetWorkTools : NSObject
-(void)netWorkWithUrl:(void(^)(NSString *urlStr))urlStr;
@end
@interface NetWorkTools ()
@property (nonatomic, copy) void (^finishedBlock)(NSString *);
@end
-(void)netWorkWithUrl:(void(^)(NSString *urlStr))urlStr{
// 1. 使用属性记录 block
self.finishedBlock = urlStr;
}
在ViewController来调用这个类
@interface SecViewController ()
@property(nonatomic,strong)NetWorkTools *tool;
@end
- (void)viewDidLoad {
[super viewDidLoad];
NetWorkTools *tool = [[NetWorkTools alloc] init];
self.tool = tool;
[self.tool netWorkWithUrl:^(NSString *urlStr) {
self.view.backgroundColor = [UIColor whiteColor];
}];
}
如何造成循环引用
循环引用场景2.png解决方法
@interface SecViewController ()
@property(nonatomic,strong)NetWorkTools *tool;
@end
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
NetWorkTools *tool = [[NetWorkTools alloc] init];
self.tool = tool;
[self.tool netWorkWithUrl:^(NSString *urlStr) {
weakSelf.view.backgroundColor = [UIColor whiteColor];
}];
}
写在最后
其实有的时候并没有造成循环引用,举个例子
//这个是GCD的延迟调用方法,并没有造成循环引用
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.view.backgroundColor = [UIColor whiteColor];
});
所以分析是不是循环引用还是多在项目中实践,坑踩得多了自然就懂了,虽然我这个方法很不可取