其中有兩點需要注意:
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 對於...