IOS中(assign,retain,copy,weak,strong)的区别以及nonatomic的含义

我们在声明@property 属性时,总是要在括号中写上assign、retain、copy、weak、strong中的一个,很多时候,我们仅仅只是按照习惯去写经常写的那一个,但有时候看代码时又会发现别人用的不尽相同,那这些之间的区别是什么呢?
首先,上面五个并不是在一个层面上的,可以分为两部分,第一部分是assign、retain、copy,第二部分是weak、strong。
我们先说第一部分的assign、retain、copy。
assign:
assign一般用来修饰基本的数据类型,包括基础数据类型 (NSInteger,CGFloat)和C数据类型(int, float, double, char, 等等),为什么呢?assign声明的属性是不会增加引用计数的,也就是说声明的属性释放后,就没有了,即使其他对象用到了它,也无法留住它,只会crash。但是,即使被释放,指针却还在,成为了野指针,如果新的对象被分配到了这个内存地址上,又会crash,所以一般只用来声明基本的数据类型,因为它们会被分配到栈上,而栈会由系统自动处理,不会造成野指针。
retain:
与assign相对,我们要解决对象被其他对象引用后释放造成的问题,就要用retain来声明。retain声明后的对象会更改引用计数,那么每次被引用,引用计数都会+1,释放后就会-1,即使这个对象本身释放了,只要还有对象在引用它,就会持有,不会造成什么问题,只有当引用计数为0时,就被dealloc析构函数回收内存了。
copy:
最常见到copy声明的应该是NSString。copy与retain的区别在于retain的引用是拷贝指针地址,而copy是拷贝对象本身,也就是说retain是浅复制,copy是深复制,如果是浅复制,当修改对象值时,都会被修改,而深复制不会。之所以在NSString这类有可变类型的对象上使用,是因为它们有可能和对应的可变类型如NSMutableString之间进行赋值操作,为了防止内容被改变,使用copy去深复制一份。copy工作由copy方法执行,此属性只对那些实现了NSCopying协议的对象类型有效 。
以上三个可以在MRC中使用,但是weak和strong就只能在ARC中使用,也就是自动引用计数,这时就不能手动去进行retain、release等操作了,ARC会帮我们完成这些工作。
(在说明白retain和copy的区别,首先需要明白深复制和浅复制的概念。
1 深拷贝:深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。
2 浅拷贝:浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。在 iOS 里面, 使用retain 关键字进行引用计数,就是一种更加保险的浅拷贝。他既让几个指针共用同一片内存空间,又可以在release 由于计数的存在,不会轻易的销毁内存,达到更加简单使用的目的。

只有不可变对象创建不可变副本(copy)才是浅复制,其它的都是深复制
下面通过实验来说明copy和retain的区别。

@interface ViewController ()@property (nonatomic,copy) NSString *name;
@property (nonatomic,retain) NSString *name2;
@end
-(void)test{ 
    NSString *str = @"fffff"; 
    self.name = str; 
    self.name2 = str; NSLog(@" str: %p",str); 
    NSLog(@" copy:  %p",self.name); 
    NSLog(@"retain: %p",self.name2);
}

-(void)test2{
     NSMutableString *str = [NSMutableString stringWithString:@"ffffff"]; 
     self.name = str; self.name2 = str;
     NSLog(@" strM: %p",str); 
     NSLog(@" copy: %p",self.name); 
     NSLog(@"retaini: %p",self.name2);
}

先执行test,再执行test2,两次执行的结果如下:

test执行结果截图
test2执行结果截图

下面来分析一下:
(1)在test中,str指向一个不可变的NSString对象,地址为0x9d040,然后str分别给name和name2赋值,由于name和name2都是NSString对象,所有都属于浅复制,赋值后都是指向str对象地址0x9d040,所有打印结果三者指向同一个对象。
(2)在test2中,str指向一个可变的NSMutableString对象,地址为0x7c140e60,然后分别给name和name2赋值,此时copy对应的name是深复制,所以会复制出另一个对象,地址为0x7c148b80。而retain对应的name2依然指向str对象地址0x7c140e60,所以打印结果是str和name2对应同一地址,name对应另一个地址。
所以得出结论:
(1)copy是创建一个新对象,两个对象内容相同,旧对象没有变化。新的对象retain为1,与旧有对象的引用计数不变。旧对象发生改变不影响新对象,copy减少对象对上下文的依赖。
(2)retain属性表示两个对象地址相同(建立一个指针,指针拷贝),内容相同,这个对象的retain值+1。两个对象要改变就一起改变。
(3)如果把一个对象赋值给另一个对象(如上面把str赋值给name或name2),如果该对象是不可变的,那么另一个对象是copy或者retain都可以,没区别;把一个对象赋值给另一个对象,如果该对象是可变的,并且希望另一个对象随着该对象变化而变化,则可以把另一个对象设置为retain(如上面把str赋值给name2);如果希望另一个对象不随着该对象变化而变化,则可以把另一个对象设置为copy(如上面把str赋值给name)。
记住一点即可,如果复制的是不可变类型,那么copy并没有开辟新的内存,而是进行了一次浅拷贝。当然了,在实际应用中,copy返回的是不可变对象,mutableCopy返回的是可变对象,除此之外,其他都不影响使用。)

weak:
weak其实类似于assign,叫弱引用,也是不增加引用计数。一般只有在防止循环引用时使用,比如父类引用了子类,子类又去引用父类。IBOutlet、Delegate一般用的就是weak,这是因为它们会在类外部被调用,防止循环引用。
strong:
相对的,strong就类似与retain了,叫强引用,会增加引用计数,类内部使用的属性一般都是strong修饰的,现在ARC已经基本替代了MRC,所以我们最常见的就是strong了。

nonatomic:
在修饰属性时,我们往往还会加一个nonatomic,这又是什么呢?它的名字叫非原子访问。对应的有atomic,是原子性的访问。我们知道,在使用多线程时为了避免在写操作时同时进行写导致问题,经常会对要写的对象进行加锁,也就是同一时刻只允许一个线程去操作它。如果一个属性是由atomic修饰的,那么系统就会进行线程保护,防止多个写操作同时进行。这有好处,但也有坏处,那就是消耗系统资源,所以对于iPhone这种小型设备,如果不是进行多线程的写操作,就可以使用nonatomic,取消线程保护,提高性能。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342

推荐阅读更多精彩内容