日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Objective-C 深复制和浅复制与NSCopying协议

發布時間:2023/12/13 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Objective-C 深复制和浅复制与NSCopying协议 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1.簡單復制只能實現淺拷貝:指針賦值,使兩個指針指向相同的一塊內存空間,操作不安全。

2. Foundation類已經遵守了<NSCopying>和 <NSMutableCopying>協議,即實現了copy和mutableCopy方法,因此Foundation對象可以使用這些方法創建對象的副本或可變副本

@protocol NSCopying

- (id)copyWithZone:(NSZone *)zone;

@end

@protocol NSMutableCopying

- (id)mutableCopyWithZone:(NSZone *)zone;

@end


3.用戶自定義類遵守<NSCopying>協議和<NSMutableCopying>協議,則必須實現copyWithZone方法和mutableCopyWithZone方法,否則該類對象無法響應copy和mutableCopy消息?

4.實現copyWithZone方法,例:

? ? ? ?

-(id)copyWithZone:(NSZone *)zone

{

???????? Student *stu = [[Student?allocWithZone:zone]initWithName:self.name?Age:self.age];

???????? return stu;

}

對應main函數中:假設已經有一個Student對象stu1;

則:Student stu2 = [stu1 copy];

實現stu2是stu1的副本,這里是深復制,stu1和stu2分別對應不同內存。

?

5. 如果你的類產生了子類,那么copyWithZone:方法也將

被繼承

Student *stu = [[Student allocWithZone: zone] init];

?該方法應該改為: Student *stu =?[[[self class]?allocWithZone: zone]init];

?如果編寫一個類的copyWithZone:方法那么子類的方法應該先調用父類的copy方法以復制繼承來的copy實例變量.


1 NSCopying與NSMutableCopying協議

用copy方法能得到字符串的不可變副本,而mutableCopy方法能得到字符串的可變副本。?

但是如果對自定義的類,我們不能直接使用copy和mutableCopy方法,需要讓類遵守NSCopying與NSMutableCopying協議,然后實現繼承自協議的copyWithZone:方法和mutableCopyWithZone:方法,這兩個方法返回的是對象本身,得到一個對象的副本。

總之,為了保證一個自定義的類的對象使用copy方法產生一個不可變的副本,需要做兩步:?

1. 讓該類繼承NSCopying協議。?

2. 在類的代碼實現部分重寫繼承自NSCopying協議的CopyWithZone:方法,該方法返回一個該類的不可變對象副本。

為了保證一個自定義的類的對象使用mutableCopy方法產生一個可變的副本,需要做兩步:?

1. 讓該類繼承NSMutableCopying協議。?

2. 在類的代碼實現部分重寫繼承自NSMutableCopying協議的mutableCopyWithZone:方法,該方法返回一個該類的可變對象副本。

2 深復制和淺復制

代碼示例如下:?

GKHUser.h

[code]#import <Foundation/Foundation.h>//繼承NSCopying和NSMutableCopying協議 @interface GKHUser : NSObject <NSCopying, NSMutableCopying> @property (nonatomic, strong) NSMutableString *name;//類似retain類型,引用計數 @property (nonatomic, assign) int age; @end

GKHUser.m

[code]#import "GKHUser.h"@implementation GKHUser//重寫copyWithZone:方法 - (id) copyWithZone:(NSZone *)zone {NSLog(@"執行copyWithZone:方法");//使用zone參數創建一個GKHUser對象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = self.name;//這里只是淺復制user.age = self.age;return user; }//重寫mutableCopyWithZone:方法 - (id) mutableCopyWithZone:(NSZone *)zone {NSLog(@"執行mutableCopyWithZone:方法");//使用zone參數創建一個GKHUser對象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = self.name;//這里只是淺復制user.age = self.age;return user; } @end

main.m

[code]#import <Foundation/Foundation.h> #import "GKHUser.h"int main(int argc, const char * argv[]) {@autoreleasepool {GKHUser *user1 = [GKHUser new];user1.name = [NSMutableString stringWithString:@"李太"];user1.age = 10;GKHUser *user2 = [user1 copy];//復制不可變副本[user1.name appendString:@"白"];user2.age = 20;NSLog(@"user1的名字為:%@", user1.name);NSLog(@"user1的年齡為:%d", user1.age);NSLog(@"user2的名字為:%@", user2.name);NSLog(@"user2的年齡為:%d", user2.age);GKHUser *user3 = [GKHUser new];user3.name = [NSMutableString stringWithString:@"張大"];user3.age = 30;GKHUser *user4 = [user3 mutableCopy];//復制可變副本[user3.name appendString:@"彪"];user4.age = 40;NSLog(@"user3的名字為:%@", user3.name);NSLog(@"user3的年齡為:%d", user3.age);NSLog(@"user4的名字為:%@", user4.name);NSLog(@"user4的年齡為:%d", user4.age);}return 0; }

運行main.m結果:

執行copyWithZone:方法?

user1的名字為:李太白?

user1的年齡為:10?

user2的名字為:李太白?

user2的年齡為:20?

執行mutableCopyWithZone:方法?

user3的名字為:張大彪?

user3的年齡為:30?

user4的名字為:張大彪?

user4的年齡為:40

我們從結果中發現,不管是可變復制還是不可變復制,最后修改副本的name屬性時候,會導致原始對象的屬性也發生修改,為什么呢?因為這里的copyWithZone:和mutableWithZone:方法中對name屬性的賦值是淺復制,如下圖:



為了達到我們的效果,GKHUser.h和main.m代碼不變,而GKHUser.m修改如下:?

GKHUser.m

[code]#import "GKHUser.h"@implementation GKHUser//重寫copyWithZone:方法 - (id) copyWithZone:(NSZone *)zone {NSLog(@"執行copyWithZone:方法");//使用zone參數創建一個GKHUser對象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = [self.name copy];//這里對name指向的對象執行深復制,復制的副本為不可變的字符串user.age = self.age;return user; }//重寫mutableCopyWithZone:方法 - (id) mutableCopyWithZone:(NSZone *)zone {NSLog(@"執行mutableCopyWithZone:方法");//使用zone參數創建一個GKHUser對象GKHUser *user = [[[self class] allocWithZone:zone] init];user.name = [self.name mutableCopy];//這里對name指向的對象執行深復制,復制的副本為可變的字符串user.age = self.age;return user; } @end

運行main.m結果:

執行copyWithZone:方法?

user1的名字為:李太白?

user1的年齡為:10?

user2的名字為:李太?

user2的年齡為:20?

執行mutableCopyWithZone:方法?

user3的名字為:張大彪?

user3的年齡為:30?

user4的名字為:張大?

user4的年齡為:40

這樣就達到了我們的目的,user2是user1的不可變副本,實現了copy方法,而user4是user3的可變副本,實現了mutableCopy方法。?

其在內存中的示意圖如下:


總結

以上是生活随笔為你收集整理的Objective-C 深复制和浅复制与NSCopying协议的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。