hello,小伙伴們!
ios中自從引入了block,代理就在慢慢淡出我們的視野,那么block的使用大家都了解嗎?它的循環(huán)引用機制大家都了解嗎?接下來我們就來聊聊這個話題.
一,介紹下簡單block的寫法.
//a,typedef 定義下的block寫法
typedef void(^cusBlock)();
@property (copy , nonatomic) cusBlock block;
//b,直接屬性定義下的block寫法
@property (copy , nonatomic) void (^customBlock)();
//還有很多寫法,大家可以參考其它牛人的寫法,這里就不做介紹了.
二,執(zhí)行block代碼塊(customBlock)
self.customBlock = ^(){
self.name = @"lili";
NSLog(@"執(zhí)行了block塊的方法");
}
}
touchesBegan后
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
if (self.customBlock) {
self.customBlock();
}
}
輸出結果:2017-02-27 19:30:46.815 text[15115:303861] 執(zhí)行了block塊的方法
三,block循環(huán)引用的結論
//先說結論,后面再來分析
如果 [block內部] 訪問了 [外部強引用] 對象A ,那么 [block內部] 會自動產生一個 [強引用引用] 對象A;
如果 [block內部] 訪問了 [外部弱引用] 對象A ,那么 [block內部] 會自動產生一個 [弱引用引用] 對象A;
四,分析循環(huán)引用,驗證結論
a,上述代碼強引用的示意圖
block強引用示意圖.png
這樣系統(tǒng)會拋出一個??錯誤
強引用警告示意圖.png
執(zhí)行完block代碼后
block執(zhí)行完成后強引用示意圖.png
這個提示告訴我們,block內部出現(xiàn)了循環(huán)引用(有強迫癥的最好解決下,免得越積越多).
b,解決辦法,大家都知道的弱引用就可以完美的解決問題了.示意圖如下
block弱引用示意圖.png
c,特殊情況
@interface BLPerson : NSObject
@property(copy, nonatomic) NSString *name;
@property (copy , nonatomic) void (^customBlock)();
@end
#import "BLPerson.h"
- (void)viewDidLoad{
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
BLPerson *p = [[BLPerson alloc]init];
__weak typeof(p)weakp = p;
p.name = @"jack";
p.customBlock = ^(){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
weakp.name = @"lili";
NSLog(@"%@==執(zhí)行了block塊的方法",weakp.name);
});
};
if (p.customBlock) {
p.customBlock();
}
}
運行結果:2017-02-28 11:17:23.519 text[4118:80908] (null)==執(zhí)行了block塊的方法
weakp.name =null,這是為什么了,在block里面我明明已經將 weakp.name = @"lili"賦值了啊.
經過分析這是因為,在執(zhí)行dispatch_after這個block中代碼的時候,由于weakp是弱引用,在這個時間差之間weakp已經被釋放了,weakp為nil,意味著nil.name就沒意義了.
解決辦法:在customBlock里面用一個強引用在引用weakp就行了;
p.customBlock = ^(){
BLPerson *p1 = weakp;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
p1.name = @"lili";
NSLog(@"%@==執(zhí)行了block塊的方法",p1.name);
});
};
輸出結果:2017-02-28 11:26:41.679 text[4280:84156] lili==執(zhí)行了block塊的方法;這個時候P1.name是有值的;
ps:在block里面定義的屬性是不會造成強引用的;
本章總結:
請大家牢記這兩個結論,理解透了沒有block會阻礙你前進的步伐.
如果 [block內部] 訪問了 [外部強引用] 對象A ,那么 [block內部] 會自動產生一個 [強引用引用] 對象A;
如果 [block內部] 訪問了 [外部弱引用] 對象A ,那么 [block內部] 會自動產生一個 [弱引用引用] 對象A;
建議以后block里面如果沒有特殊要求,建議都寫成弱引用,避免造成自己都發(fā)現(xiàn)不了的bug.本文,如有誤之處,請大家多多指教,我一定虛心學習,希望同大家共同進步.