對象的copy&mutableCopy

來源:互聯網
上載者:User

參考:

[1]參考庫:記憶體管理編程指南

將一個指標p1直接賦值給另外一個指標p2,即:p2=p1,其實p1,p2指向的同一個執行個體對象,任何對p1進行的操作都會影響p2,因為他們指向同個地址的執行個體對象。具體的就不說了,所以如果需要拷貝一個對象,而不只是指標賦值,在C++中有“拷貝建構函式”來實現此功能。objetive-c則通過copy和mutableCopy方法來實現。

首先,objetive-c中有NSCopying 和NSMutableCopying 兩種協議,分別聲明了copyWithZone和mutableCopyWithZone方法。協議:就是把若干類中具有相同功能的方法都抽象出來,定義在一起。因此任何需要copy操作的類,只需要遵從NSCopying 和NSMutableCopying協議,並實現copyWithZone和mutableCopyWithZone方法,實現對象的拷貝。

其次,方法copy產生不可修改的對象,方法mutableCopy產生可修改的對象。產生是否可修改的對象跟之前拷貝的對象是否可修改沒有關係,跟調用copy還是mutablecopy有關係。

測試代碼如下,首先LOCBird為包含NSCopying 或NSMutableCopying 協議,如下所示。

@interface LOCBird : NSObject{NSString* name_;    }@end

@implementation LOCBird- (id)init{self = [super init];if (self) {name_ = [[NSString alloc] initWithString:@"I am a Bird!!"];}return self;}- (void)dealloc{[name_release];[super dealloc];}- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector{NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];if (signature==nil) {signature = [name_ methodSignatureForSelector:aSelector];}NSUInteger argCount = [signature numberOfArguments];for (NSInteger i=0 ; i<argCount ; i++) {NSLog(@"%s" , [signature getArgumentTypeAtIndex:i]);}NSLog(@"returnType:%s ,returnLen:%d" , [signature methodReturnType] , [signature methodReturnLength]);NSLog(@"signature:%@" , signature);return signature;}- (void)forwardInvocation:(NSInvocation *)anInvocation{NSLog(@"forwardInvocation:%@" , anInvocation);SEL seletor = [anInvocation selector];if ([name_ respondsToSelector:seletor]) {[anInvocation invokeWithTarget:name_];}}@end

  建立對象並測試

LOCBird* bird1 =[[LOCBird alloc] init];LOCBird* bird2 = [bird1 copy];LOCBird* bird3 = [bird1 mutableCopy];NSLog(@"%@ %@",bird2 , NSStringFromClass([bird2 class]));NSLog(@"%@ %@",bird3 , NSStringFromClass([bird3 class]));

輸出結果如下:

2012-03-22 22:17:28.384 LOCMessageForward[1082:f803] @

2012-03-22 22:17:28.385 LOCMessageForward[1082:f803] :

2012-03-22 22:17:28.385 LOCMessageForward[1082:f803] ^{_NSZone=}

2012-03-22 22:17:28.386 LOCMessageForward[1082:f803] returnType:@ ,returnLen:4

2012-03-22 22:17:28.387 LOCMessageForward[1082:f803] signature:<NSMethodSignature: 0x685ae90>

2012-03-22 22:17:28.388 LOCMessageForward[1082:f803] forwardInvocation:<NSInvocation: 0x6a45670>

2012-03-22 22:17:28.389 LOCMessageForward[1082:f803] @

2012-03-22 22:17:28.390 LOCMessageForward[1082:f803] :

2012-03-22 22:17:28.391 LOCMessageForward[1082:f803] ^{_NSZone=}

2012-03-22 22:17:28.392 LOCMessageForward[1082:f803] returnType:@ ,returnLen:4

2012-03-22 22:17:28.393 LOCMessageForward[1082:f803] signature:<NSMethodSignature: 0x685ae90>

2012-03-22 22:17:28.393 LOCMessageForward[1082:f803] forwardInvocation:<NSInvocation: 0x68438b0>

2012-03-22 22:17:28.394 LOCMessageForward[1082:f803] I am a Bird!! __NSCFConstantString

2012-03-22 22:17:28.395 LOCMessageForward[1082:f803] I am a Bird!! __NSCFString

因為LOCBird為遵從NSCopying 或NSMutableCopying 協議,所以不能響應copy訊息,但由於重載了methodSignatureForSelector和forwardInvocation,實現將訊息轉寄給NSString的name_成員,因此最後拷貝產生的NSString對象。

修改後遵從NSCopying 或NSMutableCopying 協議,輸出如下:

2012-03-22 22:41:09.438 LOCMessageForward[1196:f803] <LOCBird: 0x6a6c760> LOCBird

2012-03-22 22:41:09.439 LOCMessageForward[1196:f803] <LOCBird: 0x687c880> LOCBird

最後測試NSString和NSarray的拷貝方法

NSString* str1 = @"hello";NSString* str2 = @"hello";NSString* str3 = [NSString stringWithString:@"hello"];NSString* str4 = [NSString stringWithFormat:@"hello"];NSString* str5 = [[NSString alloc]initWithString:@"hello"];NSString* str6 = [[NSString alloc]initWithFormat:@"hello"];NSString* str7 = [NSString stringWithCString:"hello" encoding:NSUTF8StringEncoding];NSString* str8 = [NSString stringWithCString:"hello" encoding:NSUTF8StringEncoding];NSLog(@"%p,%p,%p,%p,%p,%p,%p,%p",str1,str2,str3,str4,str5,str6,str7,str8);NSString* cpStr1 = [str1 copy];NSMutableString* cpStr2 = [str1 mutableCopy];NSLog(@"cpStr1=%p mutCpStr1=%p",cpStr1 , cpStr2);NSArray* array = [NSArray arrayWithObjects:str1,str2,str3,str4,str5,str6,str7,str8,nil];NSArray* imArray = [array copy];for (NSString* str in imArray) {NSLog(@"%p %@",str,str);}NSLog(@"-----------------");NSMutableArray* mutArray = [array mutableCopy];[mutArray addObject:@"hello"];for (NSString* str in mutArray) {NSLog(@"%p %@",str,str);}

輸出結果如下:

0x4640,0x4640,0x4640,0x6a69860,0x4640,0x6a65a50,0x6a6b7a0,0x6a6aec0

2012-03-22 22:41:06.906 LOCMessageForward[1196:f803] cpStr1=0x4640 mutCpStr1=0x68695f0

2012-03-22 22:41:06.906 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.907 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.907 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.908 LOCMessageForward[1196:f803] 0x6a69860 hello

2012-03-22 22:41:06.908 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.909 LOCMessageForward[1196:f803] 0x6a65a50 hello

2012-03-22 22:41:06.909 LOCMessageForward[1196:f803] 0x6a6b7a0 hello

2012-03-22 22:41:06.910 LOCMessageForward[1196:f803] 0x6a6aec0 hello

2012-03-22 22:41:06.910 LOCMessageForward[1196:f803] -----------------

2012-03-22 22:41:06.911 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.911 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.912 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.912 LOCMessageForward[1196:f803] 0x6a69860 hello

2012-03-22 22:41:06.912 LOCMessageForward[1196:f803] 0x4640 hello

2012-03-22 22:41:06.913 LOCMessageForward[1196:f803] 0x6a65a50 hello

2012-03-22 22:41:06.913 LOCMessageForward[1196:f803] 0x6a6b7a0 hello

2012-03-22 22:41:06.914 LOCMessageForward[1196:f803] 0x6a6aec0 hello

2012-03-22 22:41:06.914 LOCMessageForward[1196:f803] 0x4640 hello

注意,由於“hello”為常量字串,編譯後被放在常量資料區,因此str1和str2具有相同的指標地址,但是stringWithString和stringWithFormat為啥表現不同就不明白了,不知道但是蘋果那班人怎麼想的?

可以肯定的是NSString和NSArray都是進行的淺拷貝,只拷貝指標,並增加指標所指執行個體的retainCount,並未複製該對象。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.