Objective-c下的深拷貝、淺拷貝以及NSCopying協議
阿新 • • 發佈:2019-01-24
深拷貝&淺拷貝
無論使用什麼語言程式設計我們都必須考慮深拷貝和淺拷貝的問題,只是Objective-c提供了一個實現深拷貝的標準機制而已。所謂淺拷貝其實就是指標的賦值,例如:
NSString* str1 = @"Hello World!";
NSString* str2 = str1;
此時str1和str2同時指向了記憶體中的同一片區域,無論使用哪個指標對該區域進行了改動,使用另一個指標獲取到的內容也會隨之變化。這就是所謂的淺拷貝。而所謂的深拷貝是重新申請一塊區域,重新建立一個物件,同時將原有物件的內容全部複製過來。例如:
NSString* str1 = @"Hello World!" NSString* str2 = [str1 copy];
此時,無論操作哪個指標對其內容進行修改,另外一個指標所指示的內容不會受到影響。這裡多說一句,呼叫NSString的copy函式複製出來的物件實際和原有物件指向的是同一片區域。但是如果如果對其指向的內容進行修改的話,因為NSString屬於不可改變(immutable)物件,所以系統會重新申請一片空間,寫入修改後的內容返回給該指標。而另外一個指向原來區域的指標不受任何影響。如下:
int main(int argc, const char * argv[]) { @autoreleasepool { NSString* str = @"hello world"; NSString* str1 = [str copy]; NSLog(@"str:%p, str1:%p", str, str1); str = @"liyazhou"; NSLog(@"str:%@, str1:%@", str, str1); NSLog(@"str:%p, str1:%p", str, str1); } return 0; }
得到的結果是:
NSCopying&NSMutableCopying協議
之所以可以在Objective-c下使用copy和mutablecopy函式進行物件的拷貝是因為Objective-c實現了NSCopying和NSMutableCopying協議,這兩個協議規定了對其所屬物件進行復制的具體操作:@protocol NSCopying - (id)copyWithZone:(nullable NSZone *)zone; @end @protocol NSMutableCopying - (id)mutableCopyWithZone:(nullable NSZone *)zone; @end
這兩個協議分別聲明瞭一個方法,而具體的複製操作就在這兩個方法中實現。例如呼叫NSString的copy操作實際就是執行了NSString的copyWithZone函式。
對於常用的型別,這兩個協議都已經實現,所以使用者只需要呼叫copy和mutableCopy方法即可,但是對於自定義的類,要想使用copy方法就必須自己實現該協議。例如:
#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCopying>
{
}
@property (nonatomic, strong) NSString* name;
@property (nonatomic) int age;
-(instancetype)init;
-(id)copyWithZone:(NSZone *)zone;
@end
#import "Person.h"
@implementation Person
-(instancetype)init
{
self = [super init];
if(self)
{
_name = @"李牙刷兒";
_age = 25;
}
return self;
}
-(id)copyWithZone:(NSZone *)zone
{
Person *p = [[Person allocWithZone:zone]init];
p.name = self.name;
p.age = self.age;
return p;
}
@end