說明:看了很多書上的描述,對retain assign 和copy的都是草草描述,沒有談及本質,但是retain assign 和copy卻是內存管理的重要內容,所以自己總結了下,本文涉及到了Objective-C內存管理的原則,閱讀前需要了解。
retain assign copy在@propeerty中的使用實際上是通過控制set方法進行內存管理。下面詳細介紹:
1.retain:
例如:
@class Dog
@property(nonatomic,retain) Dog *dog;
注:nonatomic與atomic相對應,涉及線程,比較麻煩,這里不做贅述,讀者僅需記住,nonatomic相對于atomic來說性能高,而聲明屬性時一般默認為atomic,故需在此申明nonatomic
這里使用了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;
}
2.assign:
例如:
@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等不可變的對象,因為是重新創建了對象,并且內容不變,因此不用擔心后面的操作會對該屬性的值產生影響。
copy與retain實例分析:
假設str為對象p的屬性
@property(nonatomic,copy)NSString *str;
NSMutableSting *s = [[NSMutableSting alloc] setString:@"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也將改變。