十一大家去哪happy了,不過去哪都是開啟看人模式,這是block的第二篇文章,給大家簡單剖析一些循環(huán)引用的問題,大家下一篇想看什么可以給樓主留言或私信,都會滿足大家的
其實(shí)block是個雙面劍,用好了可以使代碼更簡潔,增加可讀性,但是往往大家忽略了循環(huán)引用的問題,所以還是希望大家要知其一,更要知其二,本著實(shí)用性為主,還是從實(shí)際項(xiàng)目中給大家介紹幾個經(jīng)典的循環(huán)引用場景.
怎么造成循環(huán)引用
兩個對象相互持有,誰也不釋放誰,就造成循環(huán)應(yīng)用了
循環(huán)引用.jpeg
循環(huán)引用場景(一)
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;
};
}
如何造成循環(huán)引用
這樣會造成循環(huán)引用,因?yàn)閟elf.testBlock和self.blockString互相都是強(qiáng)引用,導(dǎo)致互相都不釋放,我畫出兩者的關(guān)系
循環(huán)引用場景一.png
解決方法
- (void)viewDidLoad {
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
self. testBlock = ^(){
NSString *str = weakSelf.blockString;
};
}
原理:使用__weak來修飾self對象,使其在block中不被持有,破壞循環(huán)引用
打破循環(huán)引用.png
循環(huán)引用場景(二)
大家在使用網(wǎng)絡(luò)請求的時候,經(jīng)常會用到block,但是殊不知也有可能已經(jīng)循環(huán)引用了
首先創(chuàng)建一個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來調(diào)用這個類
@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];
}];
}
如何造成循環(huán)引用
循環(huán)引用場景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];
}];
}
寫在最后
其實(shí)有的時候并沒有造成循環(huán)引用,舉個例子
//這個是GCD的延遲調(diào)用方法,并沒有造成循環(huán)引用
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
self.view.backgroundColor = [UIColor whiteColor];
});
所以分析是不是循環(huán)引用還是多在項(xiàng)目中實(shí)踐,坑踩得多了自然就懂了,雖然我這個方法很不可取