NSstring為什麼使用copy copy的深度解析
阿新 • • 發佈:2018-11-22
面試中經常問到的一個題,如果只是答到copy就是會單獨複製一份,重新開闢一個地址空間。不會因為原值的修改而修改。這樣回答100分只是拿到了10分。面試官會進一步追問。直到問到你不會。。。
入門的回答以後,遞進問題。
1.那你跟我說一下copy 還有strong的區別
上程式碼
@property (nonatomic, strong) NSString *strongString; @property (nonatomic, copy) NSString *copyedString; NSMutableString *string = [NSMutableString stringWithFormat:@"aaa"]; self.strongString = string; self.copyedString = string; //string = [NSMutableString stringWithFormat:@"aaa"]; NSLog(@"origin string: %p, %p", string, &string); NSLog(@"strong string: %p, %p", _strongString, &_strongString); NSLog(@"copy string: %p, %p", _copyedString, &_copyedString); self.outputLabel.text = [NSString stringWithFormat:@"origin string:%@\n,strong string:%@\n,copy string %@",string,_strongString,_copyedString]; [string appendString:@"bbb"]; NSLog(@"origin string: %p, %p", string, &string); NSLog(@"strong string: %p, %p", _strongString, &_strongString); NSLog(@"copy string: %p, %p", _copyedString, &_copyedString); self.outputLabel.text = [NSString stringWithFormat:@"origin string:%@\n,strong string:%@\n,copy string %@",string,_strongString,_copyedString];
看一下輸出結果:
可以看到,strong string的指向記憶體地址和string是一樣的。但是copy string是不一樣的,也就是說copy但開闢了記憶體地址。從輸出結果看,copy string並沒有因為string的內容修改而改變。但是strong就被改變了。因為strong是指標拷貝(引用計數拷貝)。而copy是內容拷貝(深拷貝)
2.那什麼情況下copy 和 strong修飾,效果是一樣的。
上程式碼:
NSString *string = [NSString stringWithFormat:@"aaa"]; self.strongString = string; self.copyedString = string; //string = [NSMutableString stringWithFormat:@"aaa"]; NSLog(@"origin string: %p, %p", string, &string); NSLog(@"strong string: %p, %p", _strongString, &_strongString); NSLog(@"copy string: %p, %p", _copyedString, &_copyedString); self.outputLabel.text = [NSString stringWithFormat:@"origin string:%@\n,strong string:%@\n,copy string %@",string,_strongString,_copyedString];
可以看到 如果是不可變拷貝不可變的副本,是不會重新開闢空間。輸出就可以看到。3塊輸出的記憶體地址是一樣的。這同樣適用於陣列。
3.那如果是自定義類,你怎麼讓它具有copy功能。能大概跟我說一下ios是如何處理的
答:遵守NScoping協議,實現copywithzone方法。大致流程如下圖
4.block為什麼使用copy
block使用copy是在MRC中延續下來的,在MRC下,方法內部的block是存放在棧區,使用copy會將block拷貝到堆區。
在ARC下編譯器會自動對block進行copy,因此我們使用copy或者strong的效果是一樣的。但是我們在ARC下繼續使用copy可以提醒我們編譯器會自動幫我們實現copy的操作。
typedef void (^AlertBlock)();
@interface AwardView : UIView
@property (nonatomic,copy) AlertBlock closeBlock;
@end