參考了一些文章奋岁,感覺(jué)寫的都不夠全面思瘟,于是決定自己進(jìn)行實(shí)踐并整理,用來(lái)作為對(duì)相關(guān)知識(shí)的總結(jié)闻伶。如有不合理之處滨攻,歡迎指正。
1蓝翰、非容器型對(duì)象(例如 字符串)
屬性變量(通過(guò)修飾符)
創(chuàng)建model
@interface Fish : NSObject
@property (nonatomic,strong) NSString *strStrong;
@property (nonatomic,copy) NSString *strCopy;
@property (nonatomic,strong) NSMutableString *mutStrStrong;
@property (nonatomic,copy) NSMutableString *mutStrCopy;
@end
//可變字符串進(jìn)行賦值
NSMutableString *mutString = [NSMutableString stringWithFormat:@"1234"];
Fish *f = [[Fish alloc] init];
f.strStrong = mutString;
f.strCopy = mutString;
f.mutStrStrong = mutString;
f.mutStrCopy = mutString;
[mutString appendFormat:@"456"];
NSLog(@"內(nèi)容:%@-%@-%@",f.strStrong,f.strCopy,mutString);
NSLog(@"Mut 內(nèi)容:%@-%@-%@",f.mutStrStrong,f.mutStrCopy,mutString);
NSLog(@"指針:%p-%p-%p",f.strStrong,f.strCopy,mutString);
NSLog(@"Mut 指針:%p-%p-%p",f.mutStrStrong,f.mutStrCopy,mutString);
打印結(jié)果:
內(nèi)容:1234456-1234-1234456
Mut 內(nèi)容:1234456-1234-1234456
指針:0x1c4444a40-0xa000000343332314-0x1c4444a40
Mut 指針:0x1c4444a40-0xa000000343332314-0x1c4444a40
//總結(jié):
//strong類型變量光绕,不管是可變還是不可變,用可變字符串進(jìn)行賦值畜份,都是淺拷貝诞帐,指向同一個(gè)地址(指針拷貝),所以改變字符內(nèi)容后爆雹,對(duì)應(yīng)的內(nèi)容也發(fā)生變化(copy 或 mutableCopy 則為深拷貝)
//copy類型變量停蕉,賦值屬于深拷貝,指針地址發(fā)生變化(內(nèi)容拷貝)钙态,所以改變字符串內(nèi)容后慧起,該變量不發(fā)生變化(copy 或 mutableCopy 都是深拷貝)
//由于 f.strCopy和 f.mutStrCopy指向同一個(gè)地址,
//猜想改變一個(gè)變量值另一個(gè)也會(huì)發(fā)生變化驯绎,
//于是進(jìn)行以下操作:
//執(zhí)行[f.mutStrCopy appendFormat:@"456"] 由于f.mutStrCopy 經(jīng)過(guò)copy賦值后不可變完慧,
//所以調(diào)用可變數(shù)組方法時(shí)就會(huì)出現(xiàn)Crash (同理修飾符copy 只能用來(lái)修飾不可變類型變量)
//f.mutStrCopy = @“456”直接賦值,則指針地址發(fā)生變化(同下不可變字符串賦值)
//所以此兩種情況都不會(huì)改變copy變量?jī)?nèi)容
//不可變字符串賦值
NSString *str = @"123";
Fish *f = [[Fish alloc] init];
f.strStrong = str;
f.strCopy = str;
f.mutStrStrong = str;
f.mutStrCopy = str;
str = @"345";
NSLog(@"內(nèi)容:%@-%@-%@",f.strStrong,f.strCopy,str);
NSLog(@"Mut 內(nèi)容:%@-%@-%@",f.mutStrStrong,f.mutStrCopy,str);
NSLog(@"指針:%p-%p-%p",f.strStrong,f.strCopy,str);
NSLog(@"Mut 指針:%p-%p-%p",f.mutStrStrong,f.mutStrCopy,str);
打印結(jié)果
內(nèi)容:123-123-345
Mut 內(nèi)容:123-123-345
指針:0x104dbc2a0-0x104dbc2a0-0x104dbc2c0
Mut 指針:0x104dbc2a0-0x104dbc2a0-0x104dbc2c0
總結(jié):
無(wú)論是否可變剩失,不可變字符串賦值只是進(jìn)行淺拷貝(指針拷貝)屈尼,指向同一個(gè)地址
對(duì)源字符串進(jìn)行重新賦值,則會(huì)指向新的指針地址拴孤,但是屬性指針還是原來(lái)的地址脾歧,所以已經(jīng)賦值的變量不會(huì)發(fā)生變化
使用copy時(shí),無(wú)論傳入的源數(shù)據(jù)是否可變演熟,復(fù)制對(duì)象就是一個(gè)不可變的
使用strong修飾時(shí)鞭执,經(jīng)過(guò)賦值后司顿,該變量有可能會(huì)受到源數(shù)據(jù)的影響
2、容器型對(duì)象(例數(shù)組)
NSMutableArray *mutArr = [NSMutableArray arrayWithObjects:[NSMutableString stringWithFormat:@"1"],@"2",@"3", nil];
NSArray *arr = [mutArr copy];
NSArray *mcArr = [mutArr mutableCopy]; //返回可變類型
NSMutableArray *mutArr1 = [mutArr copy]; //返回不可變類型
NSMutableArray *mutArr2 = [mutArr mutableCopy];
NSMutableString *mutStr = mutArr.firstObject;
[mutStr appendFormat:@"23"];
NSLog(@"數(shù)據(jù) : %@-%@-%@-%@-%@",mutArr,arr,mcArr,mutArr1,mutArr2);
NSLog(@"數(shù)據(jù)地址 :%p-%p-%p-%p-%p",mutArr,arr,mcArr,mutArr1,mutArr2);
[arr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"arr %p",obj);
}];
[mcArr enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"mcArr %p",obj);
}];
[mutArr1 enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"mutArr1 %p",obj);
}];
[mutArr2 enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
NSLog(@"mutArr2 %p",obj);
}];
打印結(jié)果
數(shù)據(jù) : (
123,
2,
3
)-(
123,
2,
3
)-(
123,
2,
3
)-(
123,
2,
3
)-(
123,
2,
3
)
數(shù)據(jù)地址 :0x1c4454bb0-0x1c4454e80-0x1c4454b80-0x1c4454460-0x1c4454a00
arr 0x1c0452f30 arr 0x10072c3a0 arr 0x10072c3c0
mcArr 0x1c0452f30 mcArr 0x10072c3a0 mcArr 0x10072c3c0
mutArr1 0x1c0452f30 mutArr1 0x10072c3a0 mutArr1 0x10072c3c0
mutArr2 0x1c0452f30 mutArr2 0x10072c3a0 mutArr2 0x10072c3c0
總結(jié):
源數(shù)據(jù)容器不可變兄纺,對(duì)不可變變量進(jìn)行copy操作大溜,只是進(jìn)行對(duì)象的指針copy,該對(duì)象指向源容器指針地址估脆,容器是淺拷貝钦奋;
源數(shù)據(jù)是可變類型,則無(wú)論被賦值對(duì)象是可變還是不可變疙赠,進(jìn)行copy或者mutableCopy付材,生成不同的容器地址,容器是深拷貝圃阳;
容器內(nèi)元素都指向同一塊地址厌衔,所以元素1發(fā)生改變,容器內(nèi)元素也發(fā)生改變
容器內(nèi)元素屬于淺拷貝(copy后返回的對(duì)象是不可變類型的捍岳,mutableCopy后返回的對(duì)象是可變類型)
//- (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag;
NSArray *items_copy = [[NSArray alloc] initWithArray:mutArr copyItems:YES];
NSMutableArray *mutitems_copy = [[NSMutableArray alloc] initWithArray:mutArr copyItems:YES];
調(diào)用該方法后富寿,再次進(jìn)行以上操作,打印結(jié)果:
數(shù)據(jù) :...(
1,
2,
3
)-(
1,
2,
3
)
數(shù)據(jù)地址 :0x1c0440510-0x1c0440510-0x1c025f7d0-0x1c0440510-0x1c0440660-0x1c0444fe0-0x1c04405a0
mutArr2 0x1c0443bd0 mutArr2 0x1040c8420 mutArr2 0x1040c8440 mutArr2 0x1040c84a0
items_copy 0xa000000000000311 items_copy 0x1040c8420 items_copy 0x1040c8440
mutitems_copy 0xa000000000000311 mutitems_copy 0x1040c8420 mutitems_copy 0x1040c8440
總結(jié):
調(diào)用該方法后锣夹,容器內(nèi)元素地址發(fā)生改變作喘,內(nèi)容也沒(méi)有隨著源數(shù)據(jù)的變化而變化 所以容器和容器內(nèi)元素都是深拷貝