- @property (nonatomic, copy) void (^getCardInfo)(NSDictionary *cardInfo);
@end
兩個點: copy和 block
我將block聲明為copy的原因是在代碼塊里面我可能會使用一些本地變量, 而block一開始是放在棧上的,只有copy后才會放到堆上。
如果加copy屬性,當其所在棧被釋放的時候,這些本地變量將變得不可訪問。一旦代碼執行到block這段就會導致bad access。
brush.getCardInfo = ^(NSDictionary *info){
[self test];
}
但是這又帶來另一個問題,就是self的引用計數+1。這意味著很可能會導致循環引用。self持有brush,brush持有block,block持有self。結果就是內存泄漏。
解決辦法如下. 通過一種方式, 告訴 block 這個變量的引用計數不要+1
如果是 MRC的情況:
__block CurrentViewController *blockself = self;
brush.getCardInfo = ^(NSDictionary *info){
[blockSelf test];
}
如果是 ARC的情況:
__weak CurrentViewController *blockself = self;
brush.getCardInfo = ^(NSDictionary *info){
[blockSelf test];
}
1.解決辦法
簡而言之就是一句話的事情
__weak typeof (self) weakself = self;
經過上面的測試發現, 在加了__ weak 和__unsafe_unretained的變量引入后
TestCycleRetain方法可以正常秩序 dealloc 方法 , 而不轉換和用__block轉換的變量都會引起循環引用
因為防止循環引用的方法如下:
__unsafe_unretained TestCycleRetain *weakSelf = self;
網上大部分人的表述是"block 里面引用了 self 導致循環引用", 但是事實真的這樣的嗎? 我表示懷疑, 其實這種說話是不嚴謹的, 不一定是顯式地出現"self"字眼才會引起循環引用, 我們改一下代碼, 不通過屬性 self.arr 去訪問 arr 變量, 而是通過實例變量_ arr 去訪問, 如下
即使在你的代碼沒有顯式地出現"self", 也會出現循環引用, 只要你在 block 里用到了 self 所擁有的東西, 但對于這種情況, 目前我不知道如何排除掉循環引用 , 因為我們無法通過加__weak 聲明或者__block聲明去禁止 block 對 self 進行強引用或者強制增加引用計數, 對于 self.arr 的情況, 我們要分兩種環境去解決,
-
MRC
__block typeof(self) weakSelf = self,
-
ARC
__weak typeof(self) weakSelf = self, 其實__weak someClass *weakSelf = self也是 OK 的
解決方式與上述基本一致, 只不過將__ block 關鍵字換成了__ weak, 這樣的意思就是告訴 block, 咱們已經沒有任何的關系, 不要在內部對 self 進行 retain 了