深入理解copy關鍵字

Mitsui_發表於2018-01-02

我們在宣告NSStringNSArray等具有可變子類的屬性時,一般都會用copy關鍵字來指定它的特質。

為什麼要用copy

copy關鍵字的解釋是:此特質所表達的所屬關係與strong(為屬性設定新值時,先保留新值,並釋放舊值,然後再將新值設定上去)類似。不同的是,設定新值時,不保留新值,而是將其“拷貝”。

看上去並沒有什麼大不了的,拷貝與否好像和設定成功不成功的關係不大!但是,傳遞給設定方法的新值可能是一個可變類的例項(父類指標指向子類物件),例如,給型別為NSString的屬性設定新值時,可能會傳遞一個NSMutableString的例項。此時如果不拷貝字串,設定完屬性後,字串的值可能會在物件不知道的情況下遭人更改。所以要拷貝一份"不可變"的字串,確保物件中的字串不會無意間被改變。

理解copy的作用

舉個例子來說:

@property (nonatomic, strong) NSString *aString;

self.aString = @"test string";
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:@"hello world"];
self.aString = mutableString;
[mutableString setString:@"hahaha"];
NSLog(@"%@",_aString);
//print: hahaha
複製程式碼

我們首先宣告瞭一個不可變字串型別的屬性aString,並且給它賦了一個值,然後初始化了一個可變的字串mutableString,由於OC這門語言的多型性,即父類指標可以指向子類物件,因為NSMutableStringNSString的子類,所以,我們可以將不可變字串型別的指標self.aString指向可變字串型別的物件mutableString,然後當我們改變mutableString的值的時候,此時不可變字串self.aString的值也隨之改變,假如我們再其他較多的地方也使用了self.aString這個物件,那麼該物件的值就會在我們不知情的情況下遭到修改,然後就會造成多處使用錯誤。 下面我們對上述程式碼稍作修改:

self.aString = @"test string";
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:@"hello world"];
self.aString = [mutableString copy];
[mutableString setString:@"hahaha"];
NSLog(@"%@",_aString);
//print: hello world
複製程式碼

在將可變字串賦值給self.aString的時候,進行一步copy的操作,此時可以看到列印的資訊為hello world,這就說明,當我們修改可變物件的時候沒對不可變物件造成任何影響。 為了避免每次賦值都進行一次copy操作,有的時候也會遺漏,我們可以在宣告屬性的時候,使用copy關鍵字,copy關鍵字的作用就是每當該屬性被賦值的時候,都進行一次copy,這樣就可以保證這個物件永遠不會因為其可變子類物件的修改而被修改。例如:

@property (nonatomic, copy) NSString *aString;

self.aString = @"test string";
NSMutableString *mutableString = [[NSMutableString alloc] initWithString:@"hello world"];
self.aString = mutableString;
[mutableString setString:@"hahaha"];
NSLog(@"%@",_aString);
//print: hello world
複製程式碼

使用copy關鍵字就可以保證該屬性指向的值永遠為不可變物件。

相關文章