這裡主要側重於集合類的深淺拷貝,主要事因為工作的時候遇到這個問題。
首先我們需要有這樣的乙個前提:
[array addobject:obj];
這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。
ios對集合的記憶體處理就是這樣的。
那麼,假設obj只被array擁有:
id temp = [array objectatindex:0];
[array removeobjectatindex:0];
如果你再要使用temp就會出錯,因為這個時候obj已經被釋放了。
(提醒一下,如果用nsstring做測試,要注意@「abc」是常量 :-) )
由於在程式中經常會遇到集合類的傳值,所以,簡單的retain未必夠用,需要對集合內容的拷貝,也就是深拷貝。
下面我們就來**一下。
ios提供了copy和mutablecopy方法,顧名思義,
copy就是複製了乙個imutable的物件,而mutablecopy就是複製了乙個mutable的物件。以下將舉幾個例子來說明。
1. 系統的非容器類物件
這裡指的是nsstring,nsnumber等等一類的物件。
nsstring *string = @"origion";
nsstring *stringcopy = [string copy];
nsmutablestring *stringmcopy = [string mutablecopy];
再看下面的例子:
nsmutablestring *string = [nsmutablestring stringwithstring: @"origion"];
nsstring *stringcopy = [string copy];
nsmutablestring *mstringcopy = [string copy];
nsmutablestring *stringmcopy = [string mutablecopy];
以上四個nsstring物件所分配的記憶體都是不一樣的。但是對於mstringcopy其實是個imutable物件,所以上述會報錯。
對於系統的非容器類物件,我們可以認為,
如果對一不可變物件複製,copy是指標複製(淺拷貝)和mutablecopy就是物件複製(深拷貝)。如果是對可變物件複製,都是深拷貝,但是copy返回的物件是不可變的。
2. 系統的容器類物件
指nsarray,nsdictionary等。對於容器類本身,上面討論的結論也是適用的,需要**的是複製後容器內物件的變化。
//copy返回不可變物件,mutablecopy返回可變物件
nsarray *array1 = [nsarray arraywithobjects:@"a",@"b",@"c",nil];
nsarray *arraycopy1 = [array1 copy];
//arraycopy1是和array同乙個nsarray物件(指向相同的物件),包括array裡面的元素也是指向相同的指標
nslog(@"array1 retain count: %d",[array1 retaincount]);//marraycopy1是array1的可變副本,指向的物件和array1不同,但是其中的元素和array1中的元素指向的是同乙個物件。marraycopy1還可以修改自己的物件nslog(@"array1 retain count: %d",[arraycopy1 retaincount]);
nsmutablearray *marraycopy1 = [array1 mutablecopy];
[marraycopy1 addobject:@"de"];
[marraycopy1 removeobjectatindex:0];
array1和arraycopy1是指標複製,而marraycopy1是物件複製,marraycopy1還可以改變期內的元素:刪除或新增。但是注意的是,容器內的元素內容都是指標複製。
下面用另乙個例子來測試一下。
nsarray *marray1 = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"a"],@"b",@"c",nil];
nsarray *marraycopy2 = [marray1 copy];
nslog(@"marray1 retain count: %d",[marray1 retaincount]);
nsmutablearray *marraymcopy1 = [marray1 mutablecopy];
nslog(@"marray1 retain count: %d",[marray1 retaincount]);
//marraycopy2,marraymcopy1和marray1指向的都是不一樣的物件,但是其中的元素都是一樣的物件——同乙個指標
//一下做測試
nsmutablestring *teststring = [marray1 objectatindex:0];
//teststring = @"1a1";//這樣會改變teststring的指標,其實是將@「1a1」臨時物件賦給了teststring
由此可見,
nsarray *array = [nsarray arraywithobjects:[nsmutablestring stringwithstring:@"first"],[nsstringstringwithstring:@"b"],@"c",nil];
nsarray *deepcopyarray=[[nsarray alloc] initwitharray: array copyitems: yes];
nsarray* truedeepcopyarray = [nskeyedunarchiver unarchiveobjectwithdata:
[nskeyedarchiver archiveddatawithrootobject: array]];
或者我們自己實現深拷貝的方法(略)。
3. 自定義物件
如果是我們定義的物件,那麼我們自己要實現nscopying,nsmutablecopying這樣就能呼叫copy和mutablecopy了。舉個例子:
@inte***ce myobj : nsobject
@property (nonatomic, retain) nsmutablestring *name;
@property (nonatomic, retain) nsstring *imutablestr;
@property (nonatomic) int age;
@end
@implementation myobj
@synthesize name;
@synthesize age;
@synthesize imutablestr;
- (id)init
return self;
}- (void)dealloc
- (id)copywithzone:(nszone *)zone
- (id)mutablecopywithzone:(nszone *)zone
@end
ios 深淺拷貝學習
這裡主要側重於集合類的深淺拷貝,主要事因為工作的時候遇到這個問題。首先我們需要有這樣的乙個前提 array addobject obj 這樣obj的引用計數會增加1,如果使用remove則obj的引用計數會減一。ios對集合的記憶體處理就是這樣的。那麼,假設obj只被array擁有 id temp ...
iOS基礎 深淺拷貝
其中有兩點需要注意 1 foundation類已經遵守了和 協議,即實現了copy和mutablecopy方法,因此foundation物件可以使用這些方法建立物件的副本或可變副本,例如 nsstring nsdictionary nsarray nsmutablearr 2 在ios中並不是所有的...
深淺拷貝iOS中的
淺 復 制 在複製操作時,對於被複製的物件的每一層複製都是指標複製。深 復 制 在複製操作時,對於被複製的物件至少有一層複製是物件複製。完全複製 在複製操作時,對於被複製的物件的每一層複製都是物件複製。注 1 在複製操作時,對於物件有n層是物件複製,我們可稱作n級深複製,此處n應大於等於1。2 對於...