在使用 block 的时候,为了避免产生循环引用,通常需要使用 weakSelf 与 strongSelf,代码如下:
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
__weak __typeof__(self) weakSelf = self;
dispatch_async(queue, ^{
__typeof__(self) strongSelf = weakSelf;
[strongSelf assitFunc1];
});
问题一: 系统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;
}];
这些系统的 block 不会造成循环引用的原因是,这是个类方法,block 不被 self 持有 ,而是其他负责的对象持有,同时不产生循环引用,block 持有了 self, block 运行结束会被释放,同时释放掉对 self 的持有, 所以不存在self 和 block 的循环引用问题,不需要weak 弱引用
问题二:什么时候在 block 里面可以用 self,不需要使用 weak self
之所以需要弱引用本身,是因为怕对象之间产生循环引用,引起程序崩溃,内存泄漏!
所谓“引用循环”是指双向的强引用,所以那些“单向的强引用”(block 强引用 self )没有问题
问题三:为什么 block 里面还需要写一个 strong self,如果不写会怎么样?
在 block 中先写一个 strong self,其实是为了避免在 block 的执行过程中,突然出现 self 被释放的尴尬情况,那么多半情况下会 Crash.
总结:
1.block 不形成循环引用,并且想让block代码什么情况下都执行:两种方式:A全部使用self就行;B外面定义weak,block里面用strong,也行,多此一举。
2.block 不形成循环引用,并且想让block代码在当前VC释放的情况下不执行:两种方式:A外面定义weak,里面使用weak,然后注意nil可能会crash的地方(加判断);B外面定义weak,block里面使用strong(或者直接使用self),自己加if判断,否是在当前页面,不在当前页面不执行。
3.block 循环引用,想让block代码无论如何都执行:必用weak。block里面用strong。
4.block 循环引用,想让block代码在当前VC释放的情况下不执行:两种方式:A必用weak,block里面用strong,则自己加if判断不在当前页面就不执行;B,block里面使用weak,注意nil可能导致crash的地方。