OC 属性修饰词retain assign等

#修饰词retain、assign

***retain、assign、copy在@property中的使用实际上是通过控制set方法进行内存管理。下面详细介绍:***

1. retain

例如:

```

@class Dog

@property (nonatomic,retain) Dog *dog;

```

**注:nonatomic与atomic相对应,涉及线程,nonatomic相对atomic来说性能高,而声明属性时一般认为atomic,故需在此申明nonatmic**

这里使用了retain,那么set方法中,究竟如何体现

```

- (void)setDog:(Dog *)dog

{

if (_dog != dog) { //判断是否需要重新赋值

[_dog release]; //释放旧引用,计数器-1

_dog = [dog retain]; //重新赋值,计数器+1

}

}

```

2. assign:

例如:

```

@property (nonatomic,assign) int count;

```

这里使用了assign,那么在set方法中,究竟如何体现

```

- (void)setCount:(int)count

{

_count = count;

}

```

3. copy:

例如:

```

@property(nonatomic,copy)NSString *str;

```

这里使用了copy,那么在set方法中

```

- (void)setStr:(NSString *)str

{

if(_str != str) { //判断是否需要重新赋值

[_str release]; //释放旧引用,计数器-1

_str = [str copy]; //重新赋值,使用copy

}

}

```

##总结:

1. retain:先release旧值,在retain新值,在上例中_dog与dog最终指向同一块内存区域。

2. assign:直接赋值,不考虑内存管理。

3. copy:先release旧值,再copy新值,copy的本质为复制该内所存储的内容,重新创建一个对象赋给其相同的内容,很明显,在copy这个过程中也发生了一次retain,不过这是个全新的对象。在上例中,_str与str最终指向了不同的区域,但其内容一样。

4. 从retain、assign、copy的特点中:

retain一般适用于OC中的对象

assign一般适用于非OC对象,如int等普通类型

copy一般适用于NSString等不可变的对象,因为是重新创建了对象,并且内容不变,因此不用担心后面的操作会对该属性的值产生影响。

##实例分析:

假设str为对象p的属性

```

@property (nonatomic,copy)NSString *str;

NSMutableString *s = [[NSMutableString alloc] initWithString:@"hello"];

p.str = s; //此时,str的值为@”hello“

[s appendString:@"world"]; //此时,s的值是”hello world“,但是str的值依然为”hello“。

```

但是如果开始时str的申明为:

```

@property(nonatomic,retain)NSString *str;

```

那么,在进行完[s appendString:@"world"]之后,str的值将变为”hello world“。因为str与s共用一块内存,内容完全相同,而s是可以改变的,所以s改变后,str也将改变。

copy:建立一个索引计数为1的对象,然后释放就对象 对NSString

对NSString它指出,在赋值时使用传入值的一份拷贝。拷贝工作由copy方法执行,此属性只对那些实行了NSCopying协议的对象类型有效。

retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为1

对其他NSObject和其子类

对参数进行release旧值,再retain新值

指定retain会在赋值时唤醒传入值的retain消息。此属性只能用于Objective-C对象类型,而不能用于Core Foundation对象。(原因很明显,retain会增加对象的引用计数,而基本数据类型或者Core Foundation对象都没有引用计数)。

***注意:把对象添加到数组中时,引用计数将增加对象的引用计数次数+1***

retain的实际语法为:

- (void)setName:(NSString *)newName {

if (name != newName) {

[name release];

name = [newName retain];

}

}

copy与retain:

Copy其实是建立了一个相同的对象,而retain不是:

比如一个NSString对象,地址为0X1111,内容为@”STR“

Copy到另一个NSString之后,地址为0X2222,内容相同新的对象retain为1,旧有对象没有变化

retain到另外一个NSString之后,地址相同(建立一个指针,指针拷贝),内容当然相同,这个对象的retain值+1

也就是说retain是指针拷贝,copy是内容拷贝。

retain的set方法应该是浅复制,copy的set方法应该是深复制了

copy另一个用法:

copy是内容的拷贝,对于像NSString的确实这样

但是,如果是copy的是一个NSArray呢?

NSArray *array = [NSArray arrayWithObjects:@"hello",@"world",@"baby"];

NSArray *array2 = [array copy];

这个时候,系统的确是为array2开辟了一块内存空间,但是我们要认识到的是,array2中的每个元素,只是copy了指向array中相对应元素的指针。这便是所谓的”浅复制“。

assign:简单辅值,不更改索引计数

对基础数据类型(例如NSInteger,CGFloat)和C数据类型(int,float,double,char等)适用简单数据类型

此标记说明设置器直接进行赋值,这也是默认值。在使用垃圾收集的应用程序中,如果你要一个属性使用assign,且这个类符合NSCopying协议,你就要明白指出这个标记,而不是简单地使用默认值,否则的话,你将得到一个编译警告。这再次向编译器说明你确实需要赋值,即使它是可拷贝的。

weak和strong属性只有在你打开ARC时才会被要求使用,这时你是不能使用retain release autorelease操作,ARC会自动为你做好这些操作,但是你需要在对象属性上使用weak和strong,其中strong就相当于retain属性,而weak相当于assign。

strong关键字与retain相似,引用计数自动+1,用实例更能说明一切

@property(nonatomic,strong)NSString *string1;

@property(nonatomic,string)NSString *string2;

self.string1 = @"String1";

self.string2 = self.string1;

self.string1 = nil;

NSLog(@"String2 = %@",self.string2);

结果是:String2 = String1

***由于string2是strong定义的属性,所以引用计数+1,使得它们指向同一地址内容为:@”String1“,不可变字符串每次赋值都会重新开辟新地址。***

接着我们来看weak关键字:

如果这样声明两个属性:

@property(nonatomic,strong)NSString *string1;

@property(nonatomic,weak)NSString *string2;

self.string1 = @"String1";

self.string2 = self.string1;

self.string1 = nil;

NSLog(@"String2 = %@",self.string2);

结果是:String2 = null

***分析下,由于self.string1与self.string2指向同一地址,且string2没有retain内存地址,而self.string1 = nil释放了内存,所以string1为nil。声明为weak的指针,指针指向的地址一旦被释放,这些指针都将被赋值为nil。这样的好处能有效的防止野指针。在c/c++开发过程中,为何大牛都说指针的控件释放后,都要讲指针赋为NULL。在这儿用weak关键字帮我们做了这一步。***

##copy

特点:

1. 修改源文件的内容,不会影响副文本;

2. 修改副文本的内容,不会影响源文件;

OC中copy的作用是:利用一个源对象产生一个副本对象

特点:

1. 修改源对象的属性和行为,不会影响副本对象;

2. 修改副本对象的属性和行为,不会影响源对象。

如何使用copy功能

一个对象可以调用copy或mutableCopy方法来创建一个副本对象。

1. copy:创建的时不可变副本(NSString、NSArray、NSDictionary)。

2. mutableCopy:创建的可变副本(NSMutableString、NSMutableArray、NSMutableDictionary)。

使用copy功能的前提:

1. copy:需要遵守NSCopying协议,实现copyWithZone:方法。

```

@protocol NSCopying

- (id)copyWithZone:(NSZone *)zone;

@end

```

2. mutableCopy:需要遵守NSMutableCopy协议,实现mutableCopyWithZone:方法

```

@protocol NSMutableCopying

- (id)mutableCopyWithZone:(NSZone *)zone;

@end

```

###深复制和浅复制的区别:

**深拷贝**

特点:

1. 源对象和副本对象是不同的两个对象;

2. 源对象引用计数器不变,副本对象计数器为1(因为是新产生的)。

本质:产生了新对象

**浅拷贝**

特点:

1. 源对象和副本对象是同一对象;

2. 源对象(副本对象)引用计数+1,相当于做一次retain操作。

本质:没有产生新的对象。

常见赋值如下:![](http://oh6yavwvf.bkt.clouddn.com/00027.png)

***只有源对象和副本对象都不可变时,才是浅复制,其他都是深复制。***

```

/**

NSMutableString调用mutablecopy:深复制

*/

void mutableStringMutableCopy()

{

NSMutableString *srcStr = [NSMutableString stringWithFormat:@"age is %d",10];

NSMutableString *copyStr = [srcStr mutableCopy];

[copyStr appendString:@"abc"];

NSLog(@"srcStr=%@,copyStr=%@",srcStr,copyStr);

}

/**

NSMutableString调用copy:深复制

*/

void mutableStringCopy()

{

NSMutableString *srcStr = [NSMutableString stringWithFormat@"age is %d",10];

NSString *copyStr = [srcStr copy];

[srcStr appendString:@"abc"];

NSLog(@"srcStr=%p, copyStr=%p", srcStr, copySt);

}

/**

NSString调用mutablecopy:深复制

*/

void stringMutableCopy()

{

NSString *srcStr = [NSString stringWithFormat:@"age is %d",10];

NSMutableString *copyStr = [srcStr mutableCopy];

[copyStr appendString:@"abc"];

NSLog(@"srcStr=%@, copyStr=%@", srcStr, copyStr);

}

/**

NSString调用copy:浅复制

*/

void stringCopy()

{

//copy:产生的肯定是不可变副本

//如果是不可变对象调用copy方法产出不可变副本,那么不会产生新的对象

NSString *srcStr = [NSString stringWithFormat:@"age is %d",10];

NSString *copyStr = [srcStr copy];

NSLog(@"%p %p",srcStr,copyStr);

}

```

文章属于摘抄搬砖!

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

推荐阅读更多精彩内容