情况分析
情况一:block是控制器的属性,如果block内部没有使用weakSelf将会造成内存泄露
self.testBlock = ^(){
NSLog(@"%@",self.mapView);
};
self.testBlock();
情况二:把block内部抽出一个作为self的方法,当使用weakSelf调用这个方法,并且这个方法里有self的属性,block不会造成内存泄露
self.testBlock = ^(){
[weakSelf test];
};
-(void)test
{
NSLog(@"%@",self.mapView);
}
情况三:当block不是self的属性时,block内部使用self也不会造成内存泄露
TestBlock testBlock = ^(){
NSLog(@"%@",self.mapView);
};
[self test:testBlock];
情况四:当使用类方法有block作为参数使用时,block内部使用self也不会造成内存泄露
[WDNetwork testBlock:^(id responsObject) {
NSLog(@"%@",self.mapView);
}];
情况五:使用系统的某些block api(如UIView的block版本写动画时),是否也考虑引用循环问题?
所谓“引用循环”是指双向的强引用,所以那些“单向的强引用”(block 强引用 self )没有问题,比如这些:
[UIView animateWithDuration:duration animations:^{
[self.superview layoutIfNeeded];
}];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
self.someProperty = xyz;
}];
[[NSNotificationCenter defaultCenter] addObserverForName:@"someNotification"
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification * notification) {
self.someProperty = xyz;
}];
这些情况不需要考虑“引用循环”。
但如果你使用一些参数中可能含有 ivar 的系统 api ,如 GCD 、NSNotificationCenter就要小心一点:比如GCD 内部如果引用了 self,而且 GCD 的其他参数是 ivar,则要考虑到循环引用:
__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
__typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doSomethingElse];
} );
类似的:
__weak __typeof__(self) weakSelf = self;
_observer = [[NSNotificationCenter defaultCenter] addObserverForName:@"testKey"
object:nil
queue:nil
usingBlock:^(NSNotification *note) {
__typeof__(self) strongSelf = weakSelf;
[strongSelf dismissModalViewControllerAnimated:YES];
}];
self --> _observer --> block --> self 显然这也是一个循环引用。
网友评论