引子
我们今天不讲Block这个语法,因为作为一个合格的开发者,如果你不知道,那么实在是说不过去。接下来我就当大家都知道了,如果确实不懂,建议先去看资料吧。
Block最主要的一个注意事项,就是retain cycle
(循环引用问题),这会直接导致内存问题。一般的处理方式就是在block内使用weak 作为self指针的引用。这样block内就不会出现对self的强引用。
1. weakSelf和strongSelf的使用
请看下面这段代码
__weak __typeof(self)weakSelf = self;
AFNetworkReachabilityStatusBlock callback = ^(AFNetworkReachabilityStatus status) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.networkReachabilityStatus = status;
if (strongSelf.networkReachabilityStatusBlock) {
strongSelf.networkReachabilityStatusBlock(status);
}
};
这段代码来自于大家非常熟悉的AFNetwork框架中,功能是监测网络的,当然这个不是主要点。大家来看语法。
- 首先在block的最外层,定义一个weakSelf
- 在block在定义一个strongSelf,形成对weakSelf的引用,类型是__strong
- 在block内多次使用strongSelf 调用函数
原因
估计有的朋友都没想到还需要用strongSelf。这么写的原因就在于,如果在block内多次使用weakSelf进行调用函数或者实例变量,有可能会造成某一次调用的过程中weakSelf已经失效。例子
__weak __typeof__(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf do1];
[weakSelf do2];
});
do2在执行的过程中可能已经被释放,失效了。
2. block都会产生retain circle吗
答案是No,首先大家要理解retain circle产生的原因:A持有B,B持有A,依据OC的引用计数retain、release规则,双方各自被对方持有,谁也无法正常释放,循环引用就产生了。
A
...
-(void)dealloc{
[B release];
[super dealloc];
}
B
...
-(void)dealloc{
[A release];
[super dealloc];
}
上面的代码一目了然,释放A必须先释放B,但是B的dealloc中又需要释放A,谁也跑不掉了。
回到正题
[UIView animateWithDuration:duration animations:^{
[self.superview layoutIfNeeded];
}];
这种只是block内引用了self,单向引用,不会产生retain circle,大胆的使用self。
</br>
dispatch_async(dispatch_get_main_queue(), ^{
self.headerImageView = image;
});
dispatch_async不知道self什么时候释放,因此在调用的时候,先retain self一次,等到代码执行结束,在调用release,因此实际上并没有增加self的引用计数,也不需要担心retain circle。
网友评论