国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

iOS中的Copy

2019-11-06 09:54:54
字體:
來源:轉載
供稿:網友

iOS提供了copy與mutableCopy方法,copy就是復制了一個不可變的對象,而mutableCopy就是復制了一個可變的對象,下面通過幾個實例來演示一下。

一、非容器類對象的copy與mutableCopy

NSString *str = [NSString stringWithFormat:@"%@", @"create by "]; NSLog(@"str: %p 值:%@ 引用計數:%lu", str, str, [str retainCount]); NSString *strCopy = [str copy]; NSLog(@"strCopy: %p 值:%@ 引用計數:%lu", strCopy, strCopy, [strCopy retainCount]); NSMutableString *mStrCopy = [str mutableCopy]; NSLog(@"mStrCopy: %p 值:%@ 引用計數:%lu", mStrCopy, mStrCopy, [mStrCopy retainCount]); NSMutableString *mStrCopy2 = [mStrCopy copy]; NSLog(@"mStrCopy2:%p 值:%@ 引用計數:%lu", mStrCopy2, mStrCopy2, [mStrCopy2 retainCount]); //下面一句代碼不注釋則引起crash// [mStrCopy2 appendString:@"xiangpuhua"];// NSLog(@"mStrCopy2:%p 值:%@ 引用計數:%lu", mStrCopy2, mStrCopy2, [mStrCopy2 retainCount]); [mStrCopy appendString:@"xiangpuhua"]; NSLog(@"mStrCopy:%p 值:%@ 引用計數:%lu", mStrCopy, mStrCopy, [mStrCopy retainCount]); NSMutableString *mStrCopy3 = [mStrCopy mutableCopy]; NSLog(@"mStrCopy3:%p 值:%@ 引用計數:%lu", mStrCopy3, mStrCopy3, [mStrCopy3 retainCount]); [mStrCopy3 appendString:@"!!!"]; NSLog(@"mStrCopy3:%p 值:%@ 引用計數:%lu", mStrCopy3, mStrCopy3, [mStrCopy3 retainCount]);

輸出結果:

2017-02-27 17:49:42.859 CopyTest[12206:2131173] str: 0x60000002ade0 值:create by 引用計數:12017-02-27 17:49:42.859 CopyTest[12206:2131173] strCopy: 0x60000002ade0 值:create by 引用計數:22017-02-27 17:49:42.860 CopyTest[12206:2131173] mStrCopy: 0x600000074940 值:create by 引用計數:12017-02-27 17:49:42.861 CopyTest[12206:2131173] mStrCopy2:0x60000002ae20 值:create by 引用計數:12017-02-27 17:49:42.861 CopyTest[12206:2131173] mStrCopy:0x600000074940 值:create by xiangpuhua 引用計數:12017-02-27 17:49:42.861 CopyTest[12206:2131173] mStrCopy3:0x600000074a40 值:create by xiangpuhua 引用計數:12017-02-27 17:49:42.861 CopyTest[12206:2131173] mStrCopy3:0x600000074a40 值:create by xiangpuhua!!! 引用計數:1

由輸出結果,我們可知,str與strCopy指向同一內存區域,此時str與strCopy的引用計數一樣都為2。而mStrCopy則是真正意義上的復制,系統為其分配了新的內存,但指針所指向的字符串還是和str所指的一樣。而對mStrCopy進行copy的時候發現mStrCopy2與mStrCopy指向不是同一個指針,說明也是進行了真正意義上的復制,由此我們可以得出以下結論: 1、對不可變對象復制,copy是指針復制(淺拷貝),而mutableCopy是對象復制(深拷貝) 2、對可變對象復制,copy與mutableCopy都是對象復制(深拷貝)。 3、對可變對象復制,copy出來的對象是不可變的。

二、容器類對象的copy與mutableCopy

容器類對象指的是NSArray、NSDictionary等。

NSArray *arr = @[@"a"]; NSLog(@"arr: %p 值:%@ 引用計數:%lu", arr, arr, [arr retainCount]); NSArray *arrCopy = [arr copy]; NSLog(@"arrCopy: %p 值:%@ 引用計數:%lu", arrCopy, arrCopy, [arrCopy retainCount]); NSMutableArray *mArrCopy = [arr mutableCopy]; NSLog(@"mArrCopy: %p 值:%@ 引用計數:%lu", mArrCopy, mArrCopy, [mArrCopy retainCount]); NSMutableArray *mArrCopy2 = [mArrCopy copy]; NSLog(@"mArrCopy2:%p 值:%@ 引用計數:%lu", mArrCopy2, mArrCopy2, [mArrCopy2 retainCount]); //下面一句代碼不注釋則引起crash// [mArrCopy2 addObject:@"b"];// NSLog(@"mArrCopy2:%p 值:%@ 引用計數:%lu", mArrCopy2, mArrCopy2, [mArrCopy2 retainCount]); [mArrCopy addObject:@"c"]; NSLog(@"mArrCopy:%p 值:%@ 引用計數:%lu", mArrCopy, mArrCopy, [mArrCopy retainCount]); NSMutableArray *mArrCopy3 = [mArrCopy mutableCopy]; NSLog(@"mArrCopy3:%p 值:%@ 引用計數:%lu", mArrCopy3, mArrCopy3, [mArrCopy3 retainCount]); [mArrCopy3 addObject:@"d"]; NSLog(@"mArrCopy3:%p 值:%@ 引用計數:%lu", mArrCopy3, mArrCopy3, [mArrCopy3 retainCount]);

輸出結果:

2017-02-27 18:01:32.190 ffm[12459:2216832] arr: 0x60000001d6d0 值:( a) 引用計數:12017-02-27 18:01:32.190 ffm[12459:2216832] arrCopy: 0x60000001d6d0 值:( a) 引用計數:22017-02-27 18:01:32.191 ffm[12459:2216832] mArrCopy: 0x600000248940 值:( a) 引用計數:12017-02-27 18:01:32.191 ffm[12459:2216832] mArrCopy2:0x60800001d360 值:( a) 引用計數:12017-02-27 18:01:32.191 ffm[12459:2216832] mArrCopy:0x600000248940 值:( a, c) 引用計數:12017-02-27 18:01:32.192 ffm[12459:2216832] mArrCopy3:0x608000242dc0 值:( a, c) 引用計數:12017-02-27 18:01:32.192 ffm[12459:2216832] mArrCopy3:0x608000242dc0 值:( a, c, d) 引用計數:1

由輸出結果可知:容器類基本規則與非容器類一致,遵循一下規則 1、對不可變對象復制,copy是指針復制(淺拷貝),而mutableCopy是對象復制(深拷貝) 2、對可變對象復制,copy與mutableCopy都是對象復制(深拷貝)。 3、對可變對象復制,copy出來的對象是不可變的。 但是我們需要研究的是復制后容器內對象的變化。

NSArray *arr = @[[NSMutableString stringWithString:@"create by "], [NSString stringWithFormat:@"%@", @"xph"]]; NSLog(@"arr: %p 值:%@ 引用計數:%lu", arr, arr, [arr retainCount]); for (int i=0; i<arr.count; i++) { id object = arr[i]; NSLog(@"arr中第%d個元素: %p 值:%@ 引用計數:%lu", i, object, object, [object retainCount]); } NSArray *arrCopy = [arr copy]; NSLog(@"arrCopy: %p 值:%@ 引用計數:%lu", arrCopy, arrCopy, [arrCopy retainCount]); for (int i=0; i<arrCopy.count; i++) { id object = arrCopy[i]; NSLog(@"arrCopy中第%d個元素: %p 值:%@ 引用計數:%lu", i, object, object, [object retainCount]); } NSMutableArray *mArrCopy = [arr mutableCopy]; NSLog(@"mArrCopy: %p 值:%@ 引用計數:%lu", mArrCopy, mArrCopy, [mArrCopy retainCount]); for (int i=0; i<mArrCopy.count; i++) { id object = mArrCopy[i]; NSLog(@"mArrCopy中第%d個元素: %p 值:%@ 引用計數:%lu", i, object, object, [object retainCount]); } NSMutableString *first = mArrCopy[0]; [first appendString:@"xiangpuhua"]; NSLog(@"arr: %p 值:%@ 引用計數:%lu", arr, arr, [arr retainCount]); for (int i=0; i<arr.count; i++) { id object = arr[i]; NSLog(@"arr中第%d個元素: %p 值:%@ 引用計數:%lu", i, object, object, [object retainCount]); }

輸出結果:

2017-02-27 18:13:49.963 CopyTest[12598:2286314] arr: 0x6080002281a0 值:( "create by ", xph) 引用計數:12017-02-27 18:13:49.963 CopyTest[12598:2286314] arr中第0個元素: 0x608000273680 值:create by 引用計數:22017-02-27 18:13:49.963 CopyTest[12598:2286314] arr中第1個元素: 0xa000000006870783 值:xph 引用計數:184467440737095516152017-02-27 18:13:49.964 CopyTest[12598:2286314] arrCopy: 0x6080002281a0 值:( "create by ", xph) 引用計數:22017-02-27 18:13:49.964 CopyTest[12598:2286314] arrCopy中第0個元素: 0x608000273680 值:create by 引用計數:22017-02-27 18:13:49.964 CopyTest[12598:2286314] arrCopy中第1個元素: 0xa000000006870783 值:xph 引用計數:184467440737095516152017-02-27 18:13:49.964 CopyTest[12598:2286314] mArrCopy: 0x60800024c4e0 值:( "create by ", xph) 引用計數:12017-02-27 18:13:49.965 CopyTest[12598:2286314] mArrCopy中第0個元素: 0x608000273680 值:create by 引用計數:32017-02-27 18:13:49.965 CopyTest[12598:2286314] mArrCopy中第1個元素: 0xa000000006870783 值:xph 引用計數:184467440737095516152017-02-27 18:13:49.965 CopyTest[12598:2286314] arr: 0x6080002281a0 值:( "create by xiangpuhua", xph) 引用計數:22017-02-27 18:13:49.965 CopyTest[12598:2286314] arr中第0個元素: 0x608000273680 值:create by xiangpuhua 引用計數:32017-02-27 18:13:49.967 CopyTest[12598:2286314] arr中第1個元素: 0xa000000006870783 值:xph 引用計數:18446744073709551615

由此可知:不管是copy還是mutableCopy,容器內元素只是實現了指針的復制(淺拷貝)。 如果要實現容器內的元素也是深拷貝,怎么辦呢?

NSArray *arr = @[@[[NSMutableString stringWithString:@"create by "]].mutableCopy, [NSMutableString stringWithString:@"iOS "], [NSString stringWithFormat:@"%@", @"xph"]]; NSArray *deepCopyArray = [[NSArray alloc] initWithArray:arr copyItems:YES]; NSArray *deepCopyArray2 = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:arr]]; NSLog(@"1: %p 值:%@ 引用計數:%lu", arr, arr, [arr retainCount]); NSLog(@"2: %p 值:%@ 引用計數:%lu", deepCopyArray, deepCopyArray, [deepCopyArray retainCount]); NSLog(@"3: %p 值:%@ 引用計數:%lu", deepCopyArray2, deepCopyArray2, [deepCopyArray2 retainCount]); for (int i=0; i<arr.count; i++) { id o1 = arr[i]; id o2 = deepCopyArray[i]; id o3 = deepCopyArray2[i]; NSLog(@"1、中第%d個元素: %p 值:%@ 引用計數:%lu", i, o1, o1, [o1 retainCount]); NSLog(@"2、中第%d個元素: %p 值:%@ 引用計數:%lu", i, o2, o2, [o2 retainCount]); NSLog(@"3、中第%d個元素: %p 值:%@ 引用計數:%lu", i, o3, o3, [o3 retainCount]); if ([o1 isKindOfClass:[NSArray class]]) { for (id oo in o1) { NSLog(@"1、子元素: %p 值:%@ 引用計數:%lu", oo, oo, [oo retainCount]); } } if ([o2 isKindOfClass:[NSArray class]]) { for (id oo in o2) { NSLog(@"2、子元素: %p 值:%@ 引用計數:%lu", oo, oo, [oo retainCount]); } } if ([o3 isKindOfClass:[NSArray class]]) { for (id oo in o3) { NSLog(@"3、子元素: %p 值:%@ 引用計數:%lu", oo, oo, [oo retainCount]); } } }

輸出結果:

2017-02-27 22:20:00.628 CopyTest[14436:3967892] 1: 0x60000005d010 值:( ( "create by " ), "iOS ", xph) 引用計數:12017-02-27 22:20:00.628 CopyTest[14436:3967892] 2: 0x60000005d040 值:( ( "create by " ), "iOS ", xph) 引用計數:12017-02-27 22:20:00.628 CopyTest[14436:3967892] 3: 0x60000005d490 值:( ( "create by " ), "iOS ", xph) 引用計數:12017-02-27 22:20:00.628 CopyTest[14436:3967892] 1、中第0個元素: 0x60000005cfe0 值:( "create by ") 引用計數:22017-02-27 22:20:00.629 CopyTest[14436:3967892] 2、中第0個元素: 0x60000000afd0 值:( "create by ") 引用計數:12017-02-27 22:20:00.629 CopyTest[14436:3967892] 3、中第0個元素: 0x60000005d2e0 值:( "create by ") 引用計數:12017-02-27 22:20:00.629 CopyTest[14436:3967892] 1、子元素: 0x600000077700 值:create by 引用計數:42017-02-27 22:20:00.629 CopyTest[14436:3967892] 2、子元素: 0x600000077700 值:create by 引用計數:42017-02-27 22:20:00.629 CopyTest[14436:3967892] 3、子元素: 0x600000077ac0 值:create by 引用計數:12017-02-27 22:20:00.629 CopyTest[14436:3967892] 1、中第1個元素: 0x600000077780 值:iOS 引用計數:22017-02-27 22:20:00.630 CopyTest[14436:3967892] 2、中第1個元素: 0xa00000020534f694 值:iOS 引用計數:184467440737095516152017-02-27 22:20:00.631 CopyTest[14436:3967892] 3、中第1個元素: 0x600000077b80 值:iOS 引用計數:12017-02-27 22:20:00.631 CopyTest[14436:3967892] 1、中第2個元素: 0xa000000006870783 值:xph 引用計數:184467440737095516152017-02-27 22:20:00.631 CopyTest[14436:3967892] 2、中第2個元素: 0xa000000006870783 值:xph 引用計數:184467440737095516152017-02-27 22:20:00.631 CopyTest[14436:3967892] 3、中第2個元素: 0xa000000006870783 值:xph 引用計數:18446744073709551615

根據輸出結果我們可知,deepCopyArray實現了一層的深拷貝,也就是說deepCopyArray實現了其內第一層元素(即數組的直接元素)的深拷貝,當數組中的元素為容器類元素時,無法實現第二層數據的深拷貝,而deepCopyArray2實現了真正的深拷貝。(官網解釋)

總結如下: 1、對不可變對象復制,copy是指針復制(淺拷貝),而mutableCopy是對象復制(深拷貝) 2、對可變對象復制,copy與mutableCopy都是對象復制(深拷貝)。 3、對可變對象復制,copy出來的對象是不可變的。 4、容器類對象copy與mutableCopy時,元素均為指針復制(淺拷貝)。 5、使用initWithArray:copyItems:且第二個參數為YES的時候實現了一層的深拷貝 6、容器類對象中的元素不可變時,對象復制(深拷貝)并沒有真正拷貝對象,而是指針的拷貝。

三、copy關鍵字

(1)NSString、NSArray、NSDictionay等經常使用copy關鍵字。 原因:因為父類指針可以指向子類對象,使用copy的目的是為了讓本對象的屬性不受外界影響,使用copy無論給我傳入是一個可變對象還是不可對象,我本身持有的就是一個不可變的副本,如果我們使用是strong,那么這個屬性就有可能指向一個可變對象,如果這個可變對象在外部被修改了,那么會影響該屬性。

//User.h文件中@PRoperty (nonatomic, strong) NSString *name;//此時若將一個可變字符串set給name,那么此時的name則指向的是一個可變字符,那么就無法保證name的不可變性 @property (nonatomic, copy) NSString *name;//此時若將一個可變字符串set給name,此時會執行[MutableString copy]內容復制,即深復制,將返回一個不可變字符串,即name指向的是一個不可變字符串,以后即使MutableString改變也不會影響name的值 例如:NSMutableString *string = [NSMutableString stringWithString:@"origin"];//copyNSString *stringCopy = [string copy];[string appendString:@"origion!"]

此時的打印結果:string:originorigion!,而stringCopy仍為:origin (2)block也經常會使用copy關鍵字 原因:block使用copy是從MRC遺留下來的“傳統”,在MRC中,方法內部的block是在棧區的,使用copy可以把它放到堆區。在ARC中寫不寫都行。對于block使用copy還是strong效果是一樣的,但寫上copy也無傷大雅,還能時刻提醒我們:編譯器自動對block進行了copy操作。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 平塘县| 天峨县| 德州市| 息烽县| 张家港市| 五指山市| 图木舒克市| 苍梧县| 化隆| 临沂市| 凤庆县| 富顺县| 诸城市| 拉萨市| 尼木县| 聂拉木县| 秭归县| 乌拉特后旗| 彰化市| 西青区| 云林县| 都江堰市| 合川市| 额敏县| 永平县| 襄垣县| 六枝特区| 如皋市| 即墨市| 雷州市| 米林县| 册亨县| 井陉县| 特克斯县| 行唐县| 金阳县| 温泉县| 云霄县| 巨鹿县| 卢氏县| 宁国市|