前言
在学习的过程,难免会用一些开源库,想要提升自己的能力,避免不了阅读和学习优秀的开源库源码,就发现一些开源库的源码中有用到__unsafe_unretained。__unsafe_unretained有什么含义,使用它有什么好处和作用。
__unsafe_unretained是什么
- 这个__unsafe_unretained 表示的是对象的一种弱引用关系
- __unsafe_unretained修饰的对象被释放后,指针不会置空,而是变成一个野指针,那么此时如果访问这个对象的话,程序就会Crash,抛出BAD_ACCESS的异常。
看到这里大家应该能想到和这个相似的__weak:
- __weak也表示的是对象的一种弱引用关系
- __weak修饰的对象被释放后,指向对象的指针会置空,也就是指向nil,不会产生野指针
__unsafe_unretained什么时候使用,为什么使用
刚说了和__weak区别,发现这个__unsafe_unretained 使用不好的话,容易产生野指针,从而抛出BAD_ACCESS的异常引发崩溃。
这个家伙使用不好容易引发崩溃,并且有__weak干嘛还使用它呢?
- __weak只支持iOS 5.0以上的才有的(这个原因可以忽略,现在最新版的xcode最低版本早就是iOS5.0以上)
- __weak会消耗一定的性能,使用__weak需要检查对象是否被释放,在追踪是否被释放的时候当然需要追踪一些信息。
- 如果一个对象有大量的__weak引用对象的时候,当对象被废弃,此时就要遍历weak表,把表里所有的指针置空,消耗一定程度cpu资源。
综上原因就是,__unsafe_unretained比__weak快,消耗cpu资源也比__weak少。
既然__unsafe_unretained容易引发野指针,那么什么时候使用它,怎么能使用好它呢。
怎么使用__unsafe_unretained
当你明确对象的生命周期的时候,可以使用__unsafe_unretained替代__weak,可以稍微提高一些性能,虽然这点性能微乎其微。但是项目中有越来越多的对象可以让你使用的__unsafe_unretained,积少成多。还是有一定提高性能作用的。
举个例子,当A拥有B对象,A消亡B也消亡,这样当B存在,A也一定会存在的时候,此时B要调用A的接口,如果不使用弱引用,就会引发循环引用造成内存泄漏,就可以通过__unsafe_unretained(我经常使用weak)保持对A的弱引用关系。
最后上一段代码来看看weak与__unsafe_unretained区别
__weak UIView *view = [UIView new];
//view此时是nil,nil调用法不会引发崩溃
view.backgroundColor = [UIColor redColor];
NSLog(@"objc --- %@",view);
打印结果
objc --- (null)
此时要是__weak改成__unsafe_unretained
__unsafe_unretained UIView *view = [UIView new];
//调用方法会引发崩溃,该对象已经内存释放了变成野指针
view.backgroundColor = [UIColor redColor];
NSLog(@"objc --- %@",view);
结尾
- 使用__weak修饰的obj对象在被释放后,指向对象的指针被置nil。
- 使用__unsafe_unretained修饰的obj对象在被释放后,指向对象的指针成为野指针了。
- 掌握好使用__unsafe_unretained,在性能和速度上会优于__weak.使用不好的话,引发崩溃(就要哭晕在厕所了)。
网友评论