iOS基礎 深淺拷貝

2021-08-01 04:23:27 字數 4069 閱讀 3812

其中有兩點需要注意:

1、foundation類已經遵守了和 協議,即實現了copy和mutablecopy方法,因此foundation物件可以使用這些方法建立物件的副本或可變副本,例如: nsstring 、 nsdictionary 、nsarray 、 nsmutablearr ...

2、在ios中並不是所有的物件都支援copy,mutablecopy,遵守nscopying 協議的類可以傳送copy訊息,遵守nsmutablecopying 協議的類才可以傳送mutablecopy訊息。假如傳送了乙個沒有遵守上訴兩協議而傳送 copy或者 mutablecopy,那麼就會發生異常。如果想自定義一下copy 那麼就必須遵守 nscopying,並且實現 copywithzone: 方法,如果想自定義一下mutablecopy 那麼就必須遵守nsmutablecopying,並且實現 mutablecopywithzone: 方法,總之想要 copy 或是mutablecopy 必須要實現 copywithzone: 或是 mutablecopywithzone: 方法 這兩個方法,協議不簽訂也沒有問題,只不過不簽訂協議沒有協議方法的**提示.

例如: 自定義乙個 person 類,當操作 copy 時,如果沒有實現 nscopying 協議,那麼會出現錯誤。

person *p1 = [[person alloc]init];

person *p2 = [p1 copy];

nslog(@"p1 為:%@ p2 為: %@", p1, p2);

實現協議方法,輸出 p1 p2 物件位址

-(id)copywithzone:(nszone *)zone

源物件型別

拷貝方法

副本物件型別

是否產生新物件

拷貝型別

ns*copy

ns*no

淺拷貝(指標拷貝

ns*mutablecopy

nsmutable*

yes深拷貝(內容拷貝)

nsmutable*

copy

ns*yes

深拷貝(內容拷貝)

nsmutable*

mutablecopy

nsmutable*

yes深拷貝(內容拷貝)

自定義物件:

自定義物件不存在可變和不可變物件,所以均為深拷貝

深拷貝 淺拷貝

通過列印上述 p1 p2 物件,我們發現,記憶體位址是不一樣的(深拷貝),這裡我們引入深拷貝和淺拷貝的概念。

淺拷貝

淺拷貝可以簡單的理解為把物件的引用複製,或者說物件的指標.指標賦值,使兩個指標指向相同的一塊記憶體空間,操作不安全。

深拷貝

深拷貝拷貝當前指標指向的物件,系統會隨機給拷貝的物件重新分配一塊記憶體,深拷貝以後,兩份物件的記憶體位址不一樣,指標指向也不一樣。深拷貝會把當前容器中的物件重新拷貝乙份放到另乙個容器中,拷貝後的指標指向新的容器。不僅拷貝了物件還把指標頁拷貝了。

只有從不可變物件copy到不可變物件的時候才是淺拷貝,其他的都是深拷貝

1、對不可變的物件進行mutablecopy操作,是進行了一次深拷貝,返回的物件是可變的物件。

2、對不可變的物件進行copy操作,進行了一次淺拷貝,返回乙個不可變的物件。

3、對可變得物件進行copy,進行了深拷貝,產生了不可變的物件副本。

4、對可變的物件進行了一次mutablecopy,是進行了一次深拷貝, 返回的物件是乙個可變的物件。

5、想要讓自定義的物件支援copy和mutablecopy那麼就要對應實現nscopying協議,和nsmutablecopying協議。

nsstring *string = @"字串";

self.anewstr = [string copy];

self.twonewstr =[string mutablecopy];

nslog(@"1*******%p", string);

nslog(@"2*******%p", _anewstr);

nslog(@"2*******%p", _twonewstr);

結果輸出

2021-01-25 09:54:01.397 oc深淺拷貝[10541:843917] 1*******0x1099bd078

2021-01-25 09:54:01.397 oc深淺拷貝[10541:843917] 2*******0x1099bd078

2021-01-25 09:54:01.398 oc深淺拷貝[10541:843917] 2*******0x7fd959f1d820

通過列印結果我們可以看出:

因為父類指標可以指向子類物件,使用 copy 的目的是為了讓本物件的屬性不受外界影響,使用 copy 無論給我傳入是乙個可變物件還是不可物件,我本身持有的就是乙個不可變的副本.

如果我們使用是 strong ,那麼這個屬性就有可能指向乙個可變物件,如果這個可變物件在外部被修改了,那麼會影響該屬性.

copy 此特質所表達的所屬關係與 strong 類似。然而設定方法並不保留新值,而是將其「拷貝」 (copy)。 當屬性型別為 nsstring 時,經常用此特質來保護其封裝性,因為傳遞給設定方法的新值有可能指向乙個 nsmutablestring 類的例項。這個類是 nsstring 的子類,表示一種可修改其值的字串,此時若是不拷貝字串,那麼設定完屬性之後,字串的值就可能會在物件不知情的情況下遭人更改。所以,這時就要拷貝乙份「不可變」 (immutable)的字串,確保物件中的字串值不會無意間變動。只要實現屬性所用的物件是「可變的」 (mutable),就應該在設定新屬性值時拷貝乙份。

nsmutablestring *string = [nsmutablestring stringwithstring:@"origin"];//copy

nsstring *stringcopy = [string copy];

stringcopy 的值也不會因此改變,但是如果不使用 copy,stringcopy 的值就會被改變。 集合類物件以此類推。 所以,

用 @property 宣告 nsstring、nsarray、nsdictionary 經常使用 copy 關鍵字,是因為他們有對應的可變型別:nsmutablestring、nsmutablearray、nsmutabledictionary,他們之間可能進行賦值操作,為確保物件中的字串值不會無意間變動,應該在設定新屬性值時拷貝乙份。

1、retain是對當前物件增加了乙個指標指向,使物件的引用計數器加1, 是進行了一次安全的淺拷貝操作。

2、copy是對當前物件進行了一次拷貝,重新拷貝了當前物件,當使用的時候減少了對當前物件的依賴

如果你的類產生了子類,那麼copywithzone:方法也將被繼承。

student *stu = [[student allocwithzone: zone] init];
該方法應該改為:

student *stu = [[[self class] allocwithzone: zone]init];
如果編寫乙個類的copywithzone:方法,那麼子類的方法應該先呼叫父類的copy方法以複製繼承來的copy例項變數.

//liming 繼承了 student 在 copy 方法中,要先呼叫父類的 copy 方法, super

liming *copy = [super copywithzone:zone];

ios 深淺拷貝學習

這裡主要側重於集合類的深淺拷貝,主要事因為工作的時候遇到這個問題。首先我們需要有這樣的乙個前提 array addobject obj 這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。ios對集合的記憶體處理就是這樣的。那麼,假設obj只被array擁有 id temp ...

ios 深淺拷貝學習

這裡主要側重於集合類的深淺拷貝,主要事因為工作的時候遇到這個問題。首先我們需要有這樣的乙個前提 array addobject obj 這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。ios對集合的記憶體處理就是這樣的。那麼,假設obj只被array擁有 id temp ...

深淺拷貝iOS中的

淺 復 制 在複製操作時,對於被複製的物件的每一層複製都是指標複製。深 復 制 在複製操作時,對於被複製的物件至少有一層複製是物件複製。完全複製 在複製操作時,對於被複製的物件的每一層複製都是物件複製。注 1 在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。2 對於...