OC 屬性修飾詞retain assign等

#修飾詞retain、assign

***retain、assign、copy在@property中的使用實(shí)際上是通過控制set方法進(jìn)行內(nèi)存管理。下面詳細(xì)介紹:***

1. retain

例如:

```

@class Dog

@property (nonatomic,retain) Dog *dog;

```

**注:nonatomic與atomic相對應(yīng),涉及線程,nonatomic相對atomic來說性能高,而聲明屬性時一般認(rèn)為atomic,故需在此申明nonatmic**

這里使用了retain,那么set方法中,究竟如何體現(xiàn)

```

- (void)setDog:(Dog *)dog

{

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

[_dog release]; //釋放舊引用,計數(shù)器-1

_dog = [dog retain]; //重新賦值,計數(shù)器+1

}

}

```

2. assign:

例如:

```

@property (nonatomic,assign) int count;

```

這里使用了assign,那么在set方法中,究竟如何體現(xiàn)

```

- (void)setCount:(int)count

{

_count = count;

}

```

3. copy:

例如:

```

@property(nonatomic,copy)NSString *str;

```

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

```

- (void)setStr:(NSString *)str

{

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

[_str release]; //釋放舊引用,計數(shù)器-1

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

}

}

```

##總結(jié):

1. retain:先release舊值,在retain新值,在上例中_dog與dog最終指向同一塊內(nèi)存區(qū)域。

2. assign:直接賦值,不考慮內(nèi)存管理。

3. copy:先release舊值,再copy新值,copy的本質(zhì)為復(fù)制該內(nèi)所存儲的內(nèi)容,重新創(chuàng)建一個對象賦給其相同的內(nèi)容,很明顯,在copy這個過程中也發(fā)生了一次retain,不過這是個全新的對象。在上例中,_str與str最終指向了不同的區(qū)域,但其內(nèi)容一樣。

4. 從retain、assign、copy的特點(diǎn)中:

retain一般適用于OC中的對象

assign一般適用于非OC對象,如int等普通類型

copy一般適用于NSString等不可變的對象,因?yàn)槭侵匦聞?chuàng)建了對象,并且內(nèi)容不變,因此不用擔(dān)心后面的操作會對該屬性的值產(chǎn)生影響。

##實(shí)例分析:

假設(shè)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;

```

那么,在進(jìn)行完[s appendString:@"world"]之后,str的值將變?yōu)椤県ello world“。因?yàn)閟tr與s共用一塊內(nèi)存,內(nèi)容完全相同,而s是可以改變的,所以s改變后,str也將改變。

copy:建立一個索引計數(shù)為1的對象,然后釋放就對象 對NSString

對NSString它指出,在賦值時使用傳入值的一份拷貝??截惞ぷ饔蒫opy方法執(zhí)行,此屬性只對那些實(shí)行了NSCopying協(xié)議的對象類型有效。

retain:釋放舊的對象,將舊對象的值賦予輸入對象,再提高輸入對象的索引計數(shù)為1

對其他NSObject和其子類

對參數(shù)進(jìn)行release舊值,再retain新值

指定retain會在賦值時喚醒傳入值的retain消息。此屬性只能用于Objective-C對象類型,而不能用于Core Foundation對象。(原因很明顯,retain會增加對象的引用計數(shù),而基本數(shù)據(jù)類型或者Core Foundation對象都沒有引用計數(shù))。

***注意:把對象添加到數(shù)組中時,引用計數(shù)將增加對象的引用計數(shù)次數(shù)+1***

retain的實(shí)際語法為:

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

if (name != newName) {

[name release];

name = [newName retain];

}

}

copy與retain:

Copy其實(shí)是建立了一個相同的對象,而retain不是:

比如一個NSString對象,地址為0X1111,內(nèi)容為@”STR“

Copy到另一個NSString之后,地址為0X2222,內(nèi)容相同新的對象retain為1,舊有對象沒有變化

retain到另外一個NSString之后,地址相同(建立一個指針,指針拷貝),內(nèi)容當(dāng)然相同,這個對象的retain值+1

也就是說retain是指針拷貝,copy是內(nèi)容拷貝。

retain的set方法應(yīng)該是淺復(fù)制,copy的set方法應(yīng)該是深復(fù)制了

copy另一個用法:

copy是內(nèi)容的拷貝,對于像NSString的確實(shí)這樣

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

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

NSArray *array2 = [array copy];

這個時候,系統(tǒng)的確是為array2開辟了一塊內(nèi)存空間,但是我們要認(rèn)識到的是,array2中的每個元素,只是copy了指向array中相對應(yīng)元素的指針。這便是所謂的”淺復(fù)制“。

assign:簡單輔值,不更改索引計數(shù)

對基礎(chǔ)數(shù)據(jù)類型(例如NSInteger,CGFloat)和C數(shù)據(jù)類型(int,float,double,char等)適用簡單數(shù)據(jù)類型

此標(biāo)記說明設(shè)置器直接進(jìn)行賦值,這也是默認(rèn)值。在使用垃圾收集的應(yīng)用程序中,如果你要一個屬性使用assign,且這個類符合NSCopying協(xié)議,你就要明白指出這個標(biāo)記,而不是簡單地使用默認(rèn)值,否則的話,你將得到一個編譯警告。這再次向編譯器說明你確實(shí)需要賦值,即使它是可拷貝的。

weak和strong屬性只有在你打開ARC時才會被要求使用,這時你是不能使用retain release autorelease操作,ARC會自動為你做好這些操作,但是你需要在對象屬性上使用weak和strong,其中strong就相當(dāng)于retain屬性,而weak相當(dāng)于assign。

strong關(guān)鍵字與retain相似,引用計數(shù)自動+1,用實(shí)例更能說明一切

@property(nonatomic,strong)NSString *string1;

@property(nonatomic,string)NSString *string2;

self.string1 = @"String1";

self.string2 = self.string1;

self.string1 = nil;

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

結(jié)果是:String2 = String1

***由于string2是strong定義的屬性,所以引用計數(shù)+1,使得它們指向同一地址內(nèi)容為:@”String1“,不可變字符串每次賦值都會重新開辟新地址。***

接著我們來看weak關(guān)鍵字:

如果這樣聲明兩個屬性:

@property(nonatomic,strong)NSString *string1;

@property(nonatomic,weak)NSString *string2;

self.string1 = @"String1";

self.string2 = self.string1;

self.string1 = nil;

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

結(jié)果是:String2 = null

***分析下,由于self.string1與self.string2指向同一地址,且string2沒有retain內(nèi)存地址,而self.string1 = nil釋放了內(nèi)存,所以string1為nil。聲明為weak的指針,指針指向的地址一旦被釋放,這些指針都將被賦值為nil。這樣的好處能有效的防止野指針。在c/c++開發(fā)過程中,為何大牛都說指針的控件釋放后,都要講指針賦為NULL。在這兒用weak關(guān)鍵字幫我們做了這一步。***

##copy

特點(diǎn):

1. 修改源文件的內(nèi)容,不會影響副文本;

2. 修改副文本的內(nèi)容,不會影響源文件;

OC中copy的作用是:利用一個源對象產(chǎn)生一個副本對象

特點(diǎn):

1. 修改源對象的屬性和行為,不會影響副本對象;

2. 修改副本對象的屬性和行為,不會影響源對象。

如何使用copy功能

一個對象可以調(diào)用copy或mutableCopy方法來創(chuàng)建一個副本對象。

1. copy:創(chuàng)建的時不可變副本(NSString、NSArray、NSDictionary)。

2. mutableCopy:創(chuàng)建的可變副本(NSMutableString、NSMutableArray、NSMutableDictionary)。

使用copy功能的前提:

1. copy:需要遵守NSCopying協(xié)議,實(shí)現(xiàn)copyWithZone:方法。

```

@protocol NSCopying

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

@end

```

2. mutableCopy:需要遵守NSMutableCopy協(xié)議,實(shí)現(xiàn)mutableCopyWithZone:方法

```

@protocol NSMutableCopying

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

@end

```

###深復(fù)制和淺復(fù)制的區(qū)別:

**深拷貝**

特點(diǎn):

1. 源對象和副本對象是不同的兩個對象;

2. 源對象引用計數(shù)器不變,副本對象計數(shù)器為1(因?yàn)槭切庐a(chǎn)生的)。

本質(zhì):產(chǎn)生了新對象

**淺拷貝**

特點(diǎn):

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

2. 源對象(副本對象)引用計數(shù)+1,相當(dāng)于做一次retain操作。

本質(zhì):沒有產(chǎn)生新的對象。

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

***只有源對象和副本對象都不可變時,才是淺復(fù)制,其他都是深復(fù)制。***

```

/**

NSMutableString調(diào)用mutablecopy:深復(fù)制

*/

void mutableStringMutableCopy()

{

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

NSMutableString *copyStr = [srcStr mutableCopy];

[copyStr appendString:@"abc"];

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

}

/**

NSMutableString調(diào)用copy:深復(fù)制

*/

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調(diào)用mutablecopy:深復(fù)制

*/

void stringMutableCopy()

{

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

NSMutableString *copyStr = [srcStr mutableCopy];

[copyStr appendString:@"abc"];

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

}

/**

NSString調(diào)用copy:淺復(fù)制

*/

void stringCopy()

{

//copy:產(chǎn)生的肯定是不可變副本

//如果是不可變對象調(diào)用copy方法產(chǎn)出不可變副本,那么不會產(chǎn)生新的對象

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

NSString *copyStr = [srcStr copy];

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

}

```

文章屬于摘抄搬磚!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容