copy和strong

一、簡單介紹
copy 表示重新建立一個新的計數(shù)為1的對象,然后釋放掉舊的值。比如NSString,copy就是新生成了一個對象;但是如果是 NSArray,NSDictionary等,copy的是其對象的指針,并沒有copy里面的內(nèi)容。strong 表示強引用,類似于retain。

二、copy & strong
在定義一個類的property時候,為property選擇strong還是copy特別注意和研究明白的,一般property是NSString的時候,會選擇使用copy屬性修飾。比如:

@interface ViewController ()<NSCopying, NSMutableCopying>
@property (nonatomic, strong) NSString *myStrongTest;
@property (nonatomic, copy) NSString *myCopyTest;
@end
@implementation ViewController
- (void)viewDidLoad {
     NSMutableString *tempTest = [NSMutableString stringWithFormat:@"abcd"];
self.myCopyTest = tempTest;
self.myStrongTest = tempTest;

NSLog(@"tempTest:%p  myCopyTest:%p", tempTest, self.myCopyTest);
NSLog(@"tempTest:%p  myStrongTest:%p", tempTest, self.myStrongTest);

[tempTest appendString:@"ef"];

NSLog(@"myCopyTest:%@", self.myCopyTest);
NSLog(@"myStrongTest:%@", self.myStrongTest);
NSLog(@"tempTest:%p  myCopyTest:%p", tempTest, self.myCopyTest);
NSLog(@"tempTest:%p  myStrongTest:%p", tempTest, self.myStrongTest);
}

輸出結(jié)果:
由此可以看出:
對源頭是NSMutableString的字符串,strong僅僅是指針引用,增加了引用計數(shù)器,這樣源頭改變的時候,用這種strong方式聲明的變量 (無論被賦值的變量是可變的還是不可變的),它也會跟著改變;而copy聲明的變量,它不會跟著源頭改變,它實際上是深拷貝。

對源頭是NSString的字符串,無論是strong聲明的變量還是copy聲明的變量,當?shù)诙卧搭^的字符串重新指向其它的地方的時候,它還是指向原來的最初的那個位置,也就是說其實二者都是指針引用,也就是淺拷貝。

另外,這兩者對內(nèi)存計數(shù)的影響都是一樣的,都會增加內(nèi)存引用計數(shù),都需要在最后的時候做處理。

所以在聲明的一個NSString *str變量的時候,把一個NSMutableString *mStr變量的賦值給它了,如果要求str跟著mStr變化,那么就用strong;如果str不能跟著mStr一起變化,那就用copy。而對于要把 NSString類型的字符串賦值給str,那兩都沒啥區(qū)別。

三、copy & mutableCopy
首先、在iOS中并不是所有的對象都支持copy,mutableCopy,遵守NSCopying 協(xié)議的類可以發(fā)送copy消息,遵守NSMutableCopying 協(xié)議的類才可以發(fā)送mutableCopy消息。假如發(fā)送了一個沒有遵守上訴兩協(xié)議而發(fā)送 copy或者 mutableCopy,那么就會發(fā)生異常。但是默認的iOS類并沒有遵守這兩個協(xié)議。如果想自定義一下copy 那么就必須遵守NSCopying,并且實現(xiàn) copyWithZone: 方法,如果想自定義一下mutableCopy 那么就必須遵守NSMutableCopying,并且實現(xiàn) mutableCopyWithZone: 方法。

1、系統(tǒng)的非容器類對象(NSString,NSNumber)首先是不可變對象:NSString

NSString *test = @"1234";
NSString *test1 = [test copy];
NSString *test2 = [test mutableCopy];
NSMutableString *test3 = [test copy];
NSMutableString *test4 = [test mutableCopy];

NSLog(@"test:%p  test1:%p", test, test1);
NSLog(@"test:%p  test2:%p", test, test2);
NSLog(@"test:%p  test3:%p", test, test3);
NSLog(@"test:%p  test4:%p", test, test4);

輸出結(jié)果:
test和test1是一個地址,也就是說copy并沒有創(chuàng)建出來一個新字符串對象;test和test2不同,說明mutableCopy創(chuàng)建出一個新字符串對象;test和test3相同,說明沒有生成新對象;test和test4不同,說明生成了新對象;

綜上所述,在字符串是直接賦值的,是否生成新對象是和右邊有關(guān)的,如果右邊是mutableCopy才會生成新對象。

可變對象:NSMutableString

NSMutableString *test = [NSMutableString stringWithFormat:@"1234"];
NSString *test0 = test;
NSString *test1 = [test copy];
NSString *test2 = [test mutableCopy];
NSMutableString *test3 = [test copy];
NSMutableString *test4 = [test mutableCopy];

[test appendString:@"56"];

NSLog(@"test:%p  test0:%p", test, test0);
NSLog(@"test:%p  test1:%p", test, test1);
NSLog(@"test:%p  test2:%p", test, test2);
NSLog(@"test:%p  test3:%p", test, test3);
NSLog(@"test:%p  test4:%p", test, test4);

NSLog(@"test0:%@", test0);
NSLog(@"test1:%@", test1);
NSLog(@"test2:%@", test2);
NSLog(@"test3:%@", test3);
NSLog(@"test4:%@", test4);

輸出結(jié)果:
以上四個NSString對象所分配的內(nèi)存都是不一樣的。對于系統(tǒng)的非容器類對象,如果對一不可變對象復(fù)制,copy是指針復(fù)制(淺拷貝)和mutableCopy就是對象復(fù)制(深拷貝)。如果是對可變對象復(fù)制,都是深拷貝,但是copy返回的對象是不可變的。
2、系統(tǒng)的容器類對象 (NSArray,NSDictionary)

容器類本身的copy mutableCopy和非容器類的一樣,主要是容器內(nèi)對象的變化關(guān)系;

NSArray *array = [NSArray arrayWithObjects:@"a",@"b",@"c",nil];
NSArray *arrayCopy = [array copy];
NSMutableArray *mArrayCopy = [array mutableCopy];

arrayCopy 是和array同一個NSArray對象(指向相同的對象),包括array里面的元素也是指向相同的指針,mArrayCopy是array的可變副 本,指向的對象和array不同,但是其中的元素和array中的元素指向的是同一個對象。mArrayCopy還可以修改自己的對象

[mArrayCopy1 addObject:@"de"];
[mArrayCopy1 removeObjectAtIndex:0];

由此可見,array和arrayCopy是指針復(fù)制,而mArrayCopy是對象復(fù)制,mArrayCopy還可以改變數(shù)組內(nèi)的元素:刪除或添加。

NSMutableArray *array2 = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *arrayCopy2 = [array2 copy];
NSMutableArray *mArrayCopy2 = [array2 mutableCopy];

NSLog(@"array2:%p  arrayCopy2:%p", array2, arrayCopy2);
NSLog(@"array2:%p  mArrayCopy2:%p", array2, mArrayCopy2);

NSMutableString *testString = [array2 objectAtIndex:0];
[testString appendString:@"tail"];

NSLog(@"array2:%@",array2);
NSLog(@"arrayCopy2:%@",arrayCopy2);
NSLog(@“mArrayCopy2:%@",mArrayCopy2);

arrayCopy2,mArrayCopy2和array2指向的都是不一樣的對象,但是其中的元素都是一樣的對象;

NSMutableString *testString = [mArray1 objectAtIndex:0];
[testString appendString:@" tail”];

這樣以上三個數(shù)組的首元素都被改變了,由此可見,對于容器而言,其元素對象始終是指針復(fù)制。

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

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

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