從iOS4.0開始,objective C中引入了block技術。block跟標準c的函數類似,block的引入使得代碼回調更加方便。
優點:
(1)、回調直接寫在需要觸發的地方,使代碼更具有連續性。
(2)、在代碼塊內部可以訪問局部變量
但是,如果block使用不慎,將引起內存泄露。
1、爲啥會引起內存泄露?
在block代碼塊裏,如果傳入了代碼塊外部的對象,block會對該對象進行retain,持有該對象,造成循環引用。
eg:
@interface TestBlockObject : NSObject
- (void)invokeBlock:(void (^)(void))testBlock;
@end
@implementation TestBlockObject
- (void)invokeBlock:(void (^)(void))testBlock{
NSLog(@"TestBlockObject");
}
@end
//調用
@interface ViewController ()
{
TestBlockObject *ob;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
ob = [TestBlockObject new];
[ob invokeBlock:^{
//引起循環引用
[self testPrint];
}];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)testPrint{
NSLog(@"哈哈");
}
@end
引起循環引用的地方
[ob invokeBlock:^{
//引起循環引用
[self testPrint];
}];
ViewController(self)持有ob,ob的block中持有self,導致了循環引用。self對象將不會被銷燬,從而ob也不會被銷燬,引起內存泄露。
2、解決循環引用方法
使用以下的代碼替換紅色代碼
__weak typeof(self) weakSelf = self;
[ob invokeBlock:^{
if (weakSelf) {
[weakSelf testPrint];
}
}];
通過將self轉換成weak對象,然後再block中使用,破壞循環引用。
3、特殊的地方
若在ViewController的viewDidLoad加入下方的代碼,是不會導致循環引用的。因爲代碼塊是類方法,ViewController沒有持有該部分內存。當block執行結束後,block就會被釋放掉,因而self就不會被持有。
[UIView animateWithDuration:0.5 animations:^{
[self testPrint];
}];