- 因?yàn)楦割愔羔樋梢灾赶蜃宇悓?duì)象,使用 copy 的目的是為了讓本對(duì)象的屬性不受外界影響,使用 copy 無(wú)論給我傳入是一個(gè)可變對(duì)象還是不可對(duì)象,我本身持有的就是一個(gè)不可變的副本.
- 如果我們使用是 strong ,那么這個(gè)屬性就有可能指向一個(gè)可變對(duì)象,如果這個(gè)可變對(duì)象在外部被修改了,那么會(huì)影響該屬性.
copy 此特質(zhì)所表達(dá)的所屬關(guān)系與 strong 類似节值。然而設(shè)置方法并不保留新值徙硅,而是將其“拷貝” (copy)榜聂。
當(dāng)屬性類型為 NSString 時(shí)搞疗,經(jīng)常用此特質(zhì)來(lái)保護(hù)其封裝性,因?yàn)閭鬟f給設(shè)置方法的新值有可能指向一個(gè) NSMutableString 類的實(shí)例。
這個(gè)類是 NSString 的子類匿乃,表示一種可修改其值的字符串桩皿,此時(shí)若是不拷貝字符串,那么設(shè)置完屬性之后幢炸,字符串的值就可能會(huì)在對(duì)象不知情的情況下遭人更改泄隔。
所以,這時(shí)就要拷貝一份“不可變” (immutable)的字符串宛徊,確保對(duì)象中的字符串值不會(huì)無(wú)意間變動(dòng)佛嬉。
只要實(shí)現(xiàn)屬性所用的對(duì)象是“可變的” (mutable),就應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份闸天。
舉例說明:
定義一個(gè)以 strong 修飾的 array:
@property (nonatomic ,readwrite, strong) NSArray *array;
然后進(jìn)行下面的操作:
NSMutableArray *mutableArray = [[NSMutableArray alloc] init];
NSArray *array = @[ @1, @2, @3, @4 ];
self.array = mutableArray;
[mutableArray removeAllObjects];
NSLog(@"%@",self.array);
[mutableArray addObjectsFromArray:array];
self.array = [mutableArray copy];
[mutableArray removeAllObjects];
NSLog(@"%@",self.array);
打印結(jié)果如下所示:
2015-09-27 19:10:32.523 CYLArrayCopyDmo[10681:713670] ()
2015-09-27 19:10:32.524 CYLArrayCopyDmo[10681:713670] ( 1, 2, 3, 4)
為了理解這種做法暖呕,首先要知道,兩種情況:
對(duì)非集合類對(duì)象的 copy 與 mutableCopy 操作苞氮;
對(duì)集合類對(duì)象的 copy 與 mutableCopy 操作湾揽。
對(duì)非集合類對(duì)象的copy操作:
在非集合類對(duì)象中:對(duì) immutable 對(duì)象進(jìn)行 copy 操作,是指針復(fù)制笼吟,mutableCopy 操作時(shí)內(nèi)容復(fù)制库物;對(duì) mutable 對(duì)象進(jìn)行 copy 和 mutableCopy 都是內(nèi)容復(fù)制。用代碼簡(jiǎn)單表示如下:
[immutableObject copy] // 淺復(fù)制
[immutableObject mutableCopy] //深復(fù)制
[mutableObject copy] //深復(fù)制
[mutableObject mutableCopy] //深復(fù)制
比如以下代碼:
NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copy
NSString *stringCopy = [string copy];
查看內(nèi)存贷帮,會(huì)發(fā)現(xiàn) string戚揭、stringCopy 內(nèi)存地址都不一樣,說明此時(shí)都是做內(nèi)容拷貝撵枢、深拷貝毫目。即使你進(jìn)行如下操作:
[string appendString:@"origion!"]
stringCopy 的值也不會(huì)因此改變,但是如果不使用 copy诲侮,stringCopy 的值就會(huì)被改變镀虐。 集合類對(duì)象以此類推。 所以用 @property 聲明 NSString沟绪、NSArray刮便、NSDictionary 經(jīng)常使用 copy 關(guān)鍵字,是因?yàn)樗麄冇袑?duì)應(yīng)的可變類型:NSMutableString绽慈、NSMutableArray恨旱、NSMutableDictionary,他們之間可能進(jìn)行賦值操作坝疼,為確保對(duì)象中的字符串值不會(huì)無(wú)意間變動(dòng)搜贤,應(yīng)該在設(shè)置新屬性值時(shí)拷貝一份。
- 集合類對(duì)象的copy與mutableCopy集合類對(duì)象是指 NSArray钝凶、NSDictionary仪芒、NSSet ... 之類的對(duì)象。下面先看集合類immutable對(duì)象使用 copy 和 mutableCopy 的一個(gè)例子:
NSArray *array = @[@[@"a", @"b"], @[@"c", @"d"]];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看內(nèi)容,可以看到 copyArray 和 array 的地址是一樣的掂名,而 mCopyArray 和 array 的地址是不同的据沈。說明 copy 操作進(jìn)行了指針拷貝,mutableCopy 進(jìn)行了內(nèi)容拷貝饺蔑。但需要強(qiáng)調(diào)的是:此處的內(nèi)容拷貝锌介,僅僅是拷貝 array 這個(gè)對(duì)象,array 集合內(nèi)部的元素仍然是指針拷貝猾警。這和上面的非集合 immutable 對(duì)象的拷貝還是挺相似的孔祸,那么mutable對(duì)象的拷貝會(huì)不會(huì)類似呢?我們繼續(xù)往下发皿,看 mutable 對(duì)象拷貝的例子:
NSMutableArray *array = [NSMutableArray arrayWithObjects:[NSMutableString stringWithString:@"a"],@"b",@"c",nil];
NSArray *copyArray = [array copy];
NSMutableArray *mCopyArray = [array mutableCopy];
查看內(nèi)存融击,如我們所料,copyArray雳窟、mCopyArray和 array 的內(nèi)存地址都不一樣尊浪,說明 copyArray、mCopyArray 都對(duì) array 進(jìn)行了內(nèi)容拷貝封救。同樣拇涤,我們可以得出結(jié)論:
在集合類對(duì)象中,對(duì) immutable 對(duì)象進(jìn)行 copy誉结,是指針復(fù)制鹅士, mutableCopy 是內(nèi)容復(fù)制;對(duì) mutable 對(duì)象進(jìn)行 copy 和 mutableCopy 都是內(nèi)容復(fù)制惩坑。但是:集合對(duì)象的內(nèi)容復(fù)制僅限于對(duì)象本身掉盅,對(duì)象元素仍然是指針復(fù)制。用代碼簡(jiǎn)單表示如下:
[immutableObject copy] // 淺復(fù)制
[immutableObject mutableCopy] //單層深復(fù)制
[mutableObject copy] //單層深復(fù)制
[mutableObject mutableCopy] //單層深復(fù)制
這個(gè)代碼結(jié)論和非集合類的非常相似以舒。
參考鏈接:iOS 集合的深復(fù)制與淺復(fù)制