ios中assign、copy 、retain、strong、weak的区别
2015-08-11 11:14
393 查看
前言
首先说明一下,没接触过iOS 4及之前版本编程的人,很可能没用过assign、retain、copy关键字,这是因为iOS 5之后添加了ARC的特性,顺便提出来新的strong、weak关键字。相比而言,weak相当于老版本的assign(基本一致),strong相当于retain(一致)。assgin、retain、copy
引用计数
在ObjC中每个对象内部都有一个与之对应的整数(retainCount),叫“引用计数器”,当一个对象在创建之后它的引用计数器为1,当调用这个对象的alloc、retain、new、copy方法之后引用计数器自动在原来的基础上加1(ObjC中调用一个对象的方法就是给这个对象发送一个消息),当调用这个对象的release方法之后它的引用计数器减1,如果一个对象的引用计数器为0,则系统会自动调用这个对象的dealloc方法来销毁这个对象。比较
关键字 | 引用计数 | set方法处理 |
---|---|---|
assign | 不变 | 直接赋值 |
retain | +1 | 先release原来到值,再retain新值 |
copy | +1 | 先release原来到值,再copy新值 |
@property (nonatomic,关键字) NSObject *a;
当使用了不同的关键字后自动实现的set方法:
assign
-(void)setA:(int)a{ _a=a; }
retain
-(void)setA:(Car *)a{ if(_a!=a){ [_a release]; _a=[a retain]; } }
copy
-(void)setA:(NSString *)a{ if(_a!=a){ [_a release]; _a=[a copy]; } }
深拷贝(mutableCopy)和浅拷贝(copy):
深拷贝就是内容拷贝,浅拷贝就是指针拷贝。copy vs retain
retain和strong都是指针拷贝。当有其他对象引用当前对象时,会拷贝一份当前对象的地址,这样它就也指向当前对象了。所以,还是同一个对象,只是retainCount+1;copy:对于不可变对象copy采用的是浅复制,引用计数器加1(其实这是编译器进行了优化,既然原来的对象不可变,复制之后的对象也不可变那么就没有必要再重新创建一个对象了);对于可变对象copy采用的是深复制,引用计数器不变(原来的对象是可变,现在要产生一个不可变的当然得重新产生一个对象);
浅复制如下:
NSString *str1 = @"123"; NSString *str2 = [str1 copy];
ARC
ARC是自iOS 5之后增加的新特性,完全消除了手动管理内存的烦琐,编译器会自动在适当的地方插入适当的retain、release、autorelease语句。你不再需要担心内存管理,因为编译器为你处理了一切。强引用和弱引用
强引用:当前对象被其他对象引用时,会执行retain操作,引用计数器+1。当retainCount=0时,该对象才会被销毁。因为我们要进行对象的内存管理,所以这是默认的引用方式。(默认是强引用)弱引用:当前对象的生命周期不被是否由其他对象引用限制,它本该什么时候销毁就什么时候被销毁。即使它的引用没断,但是当它的生存周期到了时就会被销毁。
在定义属性时,若声明为retain类型的,则就是强引用;若声明为assign类型的,则就是弱引用。后来内存管理都由ARC来完成后,若是强引用,则就声明为strong;若是弱引用,则就声明为weak。
所以说,retain和strong是一致的(声明为强引用);assign和weak是基本一致的(声明为弱引用)。之所以说它俩是基本一致是因为它俩还是有所不同的,weak严格的说应当叫“归零弱引用”,即当对象被销毁后,会自动的把它的指针置为nil,这样可以防止野指针错误。而assign销毁对象后不会把该对象的指针置nil,对象已经被销毁,但指针还在痴痴的指向它,这就成了野指针,这是比较危险的。
避免“强引用循环“的僵局:
默认的引用方式是强引用,但上面说了有时我们还得使用弱引用,那是什么情况呢?
答案,强引用循环:A对象强引用了B对象,B对象也强引用了A。因为都是强引用,也就是无论是A是B都要在对方的引用断了后才能销毁,但要断了引用,就必须对方对象销毁。就会出现这种僵局,为了避免出现这种情况,就应该有一个对象“示弱”,使其为“弱引用”。
比较常见的,视图中的父子视图之间的引用:父视图强引用子视图,子视图弱引用父视图。
总结:由于要进行内存管理的缘故,OC里的引用默认都是强引用,但为了避免出现”强引用循环僵局“,所以有了弱引用(assign)。
相关文章推荐
- GitHub发布Ipa文件|GitHub发布plist文件|GitHub发布IOS应用
- iOS跳转界面时隐藏tabBar的方法:hidesBottomBarWhenPushed
- GCD的使用与理解(2)
- iOS 9应用开发教程之ios9中实现按钮的响应
- iOS蓝牙开发入门04--服务和特征
- iOS 9 分屏多任务(3):画中画(PiP)快速入门
- iOS播放音乐文件时的操作和打断处理
- 9秒学院iOS游戏开发从掌握到拥有,你只需四步
- iOS 9 分屏多任务(2):Slide Over & Split View快速入门
- iOS开发:创建真机调试证书
- IOS开发笔记之常用的第三方库(太多了。)
- IOS视频播放器VKVideoPlayer
- iOS中.m中,@interface部分的作用
- IOS开发 @property中assign、copy 、retain等关键字的理解
- iOS开发工具——统计Crash的工具Crashlytics
- [IOS]mac远程window全屏显示
- iOS开发-策略模式
- iOS 声明属性关键字的总结
- 实战iOS 9:开发者必须掌握的三种搜索API
- **浅述IOS成员变量(Member variables)和实例变量(Instance varialbes)的区别**