1、block中为什么会出现死循环?
问题:block中为什么会出现死循环?
原因: 内存溢出。
解决方法:使用__weak来解除block对对象的强引用。这样block中的对象是弱引用,使得两个都可以释放。
实例:
1、当A对象里面强引用了B对象,B对象又强引用了A对象,这样两者的retainCount值一直都无法为0,于是内存始终无法释放,导致内存泄露。所谓的内存泄露就是本应该释放的对象,在其生命周期结束之后依旧存在。
2、这是2个对象之间的,相应的,这种循环还能存在于3,4……个对象之间,只要相互形成环,就会导致死循环的问题。
3、当然也存在自身引用自身的,当一个对象内部的一个obj,强引用的自身,也会导致循环引用的问题出现。常见的就是block里面引用的问题。
#define WeakSelf(type) __weak typeof(type) weak##type = type; People *p = [People new]; p.name = @"piter"; //弱引用 WeakSelf(p) p.MyBlock = ^(){ NSLog(@"2.%@",weakp.name); }; p.MyBlock();
2、block中为什么使用对象被提前释放?
那么这样就可以高枕无忧了吗?下面还有坑等着你:
后续问题:有些对象在还没开始使用就已经被释放。
原因: 弱引用对象本身,在还没有使用就已经被释放。
解决方法: 需要引入__strong来解决。
实例:在和GCD一起使用的时候中间就有个很大的坑,因为block中对对象是弱引用,在block中使用GCD的话,在GCD中使用的对象就是已经弱化的对象,所以会导致这个对象还没开始使用就已经被释放了。看下面例子
#define WeakSelf(type) __weak typeof(type) weak##type = type; #define StrongSelf(type) __strong typeof(type) type = weak##type; People *p = [People new]; p.name = @"piter"; WeakSelf(p) //弱引用 p.MyBlock = ^(){ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"2.%@",weakp.name); }); }; p.MyBlock();
这段代码,在block里面使用了GCD延迟调用,而在GCD代码块里面使用到了weakp这个对象,这个对象本身就是一个弱引用对象。在这里面没有使用就已经被释放了。所以像上面的代码是会输出null的。像这样的问题就需要引入__strong来解决。如下
People *p = [People new]; p.name = @"piter"; //弱引用 WeakSelf(p); p.MyBlock = ^(){ StrongSelf(p) dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ NSLog(@"2.%@“,p.name); }); }; p.MyBlock();
这样就可以输出并且对象都会被释放。
总结: 这个strong是对block内部的强引用,不会干扰到block以外。所以不会影响people 和 myblock的释放。而对block内部的弱引用people强引用,就不会导致people提前释放了。
实例: 看AFNetworking也是使用weak加strong管理block内存的.
参考链接:
3、深入研究Block用weakSelf、strongSelf、@weakify、@strongify解决循环引用