$ 問(wèn)題拋出來(lái)
1.所有自定義方法的
block
都需要__weak
嗎?
2.凡是,block
內(nèi)帶self
的都需要__weak
嗎?
3.凡是, 系統(tǒng)方法中的block
, 都不需要__weak
嗎?
看看上述問(wèn)題的反問(wèn)語(yǔ)氣, 相必語(yǔ)文過(guò)關(guān)的同學(xué)們都知道答案,一看就是 No No No ~
-> ?? 恭喜你~ right !
$ but why ?
至于原因 ??
想必大伙都知道, 互相strong
持有成了一個(gè)環(huán) , 然后就無(wú)法釋放了~
$ block 常見(jiàn)場(chǎng)景(暫時(shí)想到的一些情況, 后續(xù)想到繼續(xù)補(bǔ)充)
first, code準(zhǔn)備:
?? 一個(gè)子View -- TestOneView, 創(chuàng)建各種參數(shù)為block的方法
// TestOneView.h
#import <UIKit/UIKit.h>
typedef void(^ZYOneBlock1)();
typedef void(^ZYOneBlock2)();
@interface TestOneView : UIView
// copy修飾
@property (nonatomic, copy) ZYOneBlock1 oneBlock;
// weak修飾
@property (nonatomic, weak) ZYOneBlock1 weak_oneBlock;
// 持有 傳入的block , 但是 weak
- (void)testWeakBlock:(ZYOneBlock1) block;
// 不持有 傳入的block , 在method中直接執(zhí)行掉
- (void)testBlock2WithBlock:(ZYOneBlock2) secondblock;
@end
// TestOneView.m
#import "TestOneView.h"
@implementation TestOneView
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
// 持有 傳入的block , strong
-(void)setOneBlock:(ZYOneBlock1)oneBlock{
_oneBlock = oneBlock;
_oneBlock();
}
// 持有 傳入的block , 但是 weak
- (void)testWeakBlock:(ZYOneBlock1) block;
{
self.weak_oneBlock = block;
}
// 不持有 傳入的block , 在method中直接執(zhí)行掉
- (void)testBlock2WithBlock:(ZYOneBlock2) secondblock;
{
secondblock();
}
// 通過(guò)dealloc 檢測(cè)能否釋放
-(void)dealloc{
NSLog(@"%s",__func__);
}
@end
go on ~ , code一個(gè)被push的VC -- TestOneViewController , 即是 block縱橫所在的江湖
?????? block 出場(chǎng) ??????
-
<1> A 操作 B的bloc
(1).傳給子View的block被子view ??
strong
持有 , block塊中使用了_ivar(成員變量) 蜂莉、strong property , 處理方式如下:- (void)testStrongBlock_1{ [self.view addSubview: self.oneView]; __weak typeof(self) weakSelf = self; self.oneView.oneBlock = ^{ __strong typeof(weakSelf) strongSelf = weakSelf; strongSelf->_intType = 11; strongSelf.pArray = @[@(11)]; }; }
(2).傳入的block塊中 含有本類(lèi)的實(shí)例方法
- (void)testMethod_StrongBlock_1{ [self.view addSubview: self.oneView]; __weak typeof(self) weakSelf = self; self.oneView.oneBlock = ^{ __strong typeof(weakSelf) strongSelf = weakSelf; // method [strongSelf containSelfMethod]; }; } - (void)containSelfMethod{ _intType = 1010; self.pArray = @[@(2020)]; }
(3).傳給子view的block 被子view ??
weak
持有, 在方法內(nèi)被執(zhí)行完抄腔。無(wú)需weakSelf- (void)testWeakBlock_1{ [self.view addSubview: self.oneView]; [self.oneView testWeakBlock:^{ _intType = 111; self.pArray = @[@(1)]; }]; }
(4).傳給子view的block ?不 被子view 持有, 直接執(zhí)行掉。
無(wú)需weakSelf- (void)testParamBlock_2{ [self.view addSubview: self.oneView]; [self.oneView testBlock2WithBlock:^{ _intType = 22; self.pArray = @[@(1)]; }]; }
-
<2> A 操作 A的block
(a).block作參數(shù), ?不 被持有
- (void)testParam_SelfBlock_1{ [self testParam_SelfBlcokWith:^(NSArray * arr) { self.pArray = arr; NSLog(@"%s",__func__); }]; } - (void)testParam_SelfBlcokWith:(MyBlockOne)myBlock{ NSArray * arr = @[@"myblock1"]; myBlock(arr); }
(b).block作參數(shù), ??被持有
- (void)testCopy_SelfBlock_1{ __weak typeof(self) weakSelf = self; [self testCopy_SelfBlcokWith:^(NSArray * arr) { __strong typeof(weakSelf) strongSelf = weakSelf; strongSelf.pArray = arr; NSLog(@"%s",__func__); }]; } - (void)testCopy_SelfBlcokWith:(MyBlockOne)myBlock{ self.myBlock1 = myBlock; NSArray * arr = @[@"myblock1"]; NSLog(@"%s",__func__); sleep(1); NSLog(@"%s",__func__); self.myBlock1(arr); }
-
<3> GCD的block(系統(tǒng)的)
無(wú)需weakSelf。注意: GCD延時(shí)block, 會(huì)使VC pop后延遲釋放- (void)didMoveToParentViewController:(UIViewController *)parent{ [self.oneView removeFromSuperview]; NSLog(@"%s , %@",__func__ ,self); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"%s , %@",__func__ ,self); [self testBackTimerAfter]; // 點(diǎn)擊pop 時(shí),會(huì)延遲2s dealloc }); } - (void)testBackTimerAfter{ [self.oneView testWeakBlock:^{ NSLog(@"%s , %@",__func__ ,self); }]; __weak typeof(self) weakSelf = self; _oneView.oneBlock = ^{ __strong typeof(weakSelf) strongSelf = weakSelf; NSLog(@"%s , %@",__func__ ,strongSelf); }; }
-
<4> ?補(bǔ)充?, 對(duì)于NSTimer addTarget: self...
_weak typeof(self) weakSelf = self; _timer = [NSTimer scheduledTimerWithTimeInterval:3.0f target:weakSelf selector:@selector(timerFire:) userInfo:nil repeats:YES];
對(duì)于如上解決方式, 是有誤的,詳解 可參考 ?? 解決NSTimer/CADisplayLink的循環(huán)引用
超懶人 點(diǎn)擊 github demo 下載 調(diào)試 涕刚。
祝愿有所收獲哦 ~ _ ~