The difference between copy and retain:copy is to create a new object, retain is to create a pointer to reference the object Count plus 1. The Copy property represents the same contents as two objects, the new object retain to 1, independent of the reference count of the old object, and the old object does not change. Copy reduces the object's dependency on the context.
The Retain property indicates that two objects have the same address (creating a pointer, copy of the pointer) and, of course, the same content, the retain value of this object +1 that is, retain is a pointer copy, copy is a copy of the content.
Of course not all objects in iOS support Copy,mutablecopy, classes that follow the Nscopying protocol can send copy messages, and classes that follow the Nsmutablecopying protocol can send mutablecopy messages. If a copy or mutablecopy is sent without complying with the appeal agreement, an exception will occur. However, the default iOS class does not follow these two protocols. If you want to customize copy then you must obey Nscopying and implement Copywithzone: method, if you want to customize mutablecopy then you must obey Nsmutablecopying, and implement Mutablecopywithzone: Method.
First, we need to have such a premise:
[Array addobject:obj];
This will increase the reference count of obj by 1, and if you use remove, the reference count of obj will be reduced by one.
This is how iOS handles collections in memory.
So, suppose that obj is only owned by an array:
ID temp = [array Objectatindex:0];[ Array Removeobjectatindex:0];
If you want to use temp again, it will go wrong, because obj has been released at this time.
(Note that if you test with nsstring, be aware that @ "ABC" is a constant:-) )
Because in the program often encounters the collection class The pass value, therefore, the simple retain may not suffice, needs to the collection content copy, namely deep copy.
Let's talk about it here.
iOS provides copy and Mutablecopy methods, as the name implies, copy is copying a Imutable object, and Mutablecopy is copying a mutable object. Here are a few examples to illustrate.
1. Non-container class objects of the system
This refers to objects such as Nsstring,nsnumber and so on.
NSString *string@ "origion"*stringcopy = [string* Stringmcopy = [string mutablecopy]; [Stringmcopy appendString: @" !! "];
View memory you can see that string and stringcopy point to the same chunk of memory (also known as Apple's weak reference weak reference), at which point the reference count of Stringcopy is 2 of the same as string. And Stringmcopy is what we call the true meaning of replication, the system allocates new memory to it, but the pointer points to the same string as it refers to.
Let's look at the following example:
Nsmutablestring *string= [Nsmutablestring stringwithstring:@"origion"]; NSString*stringcopy = [stringcopy]; Nsmutablestring*mstringcopy = [stringcopy]; Nsmutablestring*stringmcopy = [stringMutablecopy]; [Mstringcopy appendString:@"mm"];//Error[stringAppendString:@"origion!"]; [Stringmcopy appendString:@"!!"];
The memory allocated by the above four NSString objects is not the same. But for Mstringcopy is actually a imutable object, so the above will be an error.
For non-container class objects of the system, we can assume that if copying an immutable object, copy is pointer copy (shallow copy) and mutablecopy is the object copy (deep copy). If it is a copy of a mutable object, it is a deep copy, but the object returned by copy is immutable.
2. System's container class object
Refers to nsarray,nsdictionary and so on. For the container class itself, the conclusions discussed above are also applicable, and it is necessary to explore the changes of objects in the container after replication.
//copy returns an immutable object, Mutablecopy returns a Mutable objectNsarray *array1 = [Nsarray arraywithobjects:@"a",@"b",@"C", nil]; Nsarray*arraycopy1 =[array1 copy]; //ArrayCopy1 is the same Nsarray object as the array (pointing to the same object), including the elements inside the array that also point to the same pointerNSLog (@"array1 retain count:%d", [array1 Retaincount]); NSLog (@"array1 retain count:%d", [ArrayCopy1 Retaincount]); Nsmutablearray*marraycopy1 =[Array1 mutablecopy]; //MArrayCopy1 is a mutable copy of Array1, which points to different objects and array1, but the elements in them and the elements in the array1 point to the same object. MArrayCopy1 can also modify their own objects[MArrayCopy1 AddObject:@"de"]; [MArrayCopy1 Removeobjectatindex:0];
Array1 and ArrayCopy1 are pointer copies, and MARRAYCOPY1 is an object copy, and mArrayCopy1 can also change elements in the period: delete or Add. Note, however, that the element content inside the container is a pointer copy.
Let's test it with another example.
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 and MArray1 point to different objects, but the elements are the same object--the same pointer//A little bit of testing.nsmutablestring *teststring = [MArray1 objectatindex:0]; //teststring = @ "1a1";//This will change the teststring pointer, in fact, the @ "1a1" temporary object assigned to the TestString[TestString appendString:@"Tail"];//so the first element of the above three arrays has been changed.
Thus, for a container, its element object is always a pointer copy. If you need an element object that is also an object copy, you need to implement a deep copy. http://developer.apple.com/library/mac/#documentation/cocoa/conceptual/collections/articles/copying.html
Nsarray *array = [Nsarray arraywithobjects:[nsmutablestring stringwithstring:@ " /span>first ],[ Nsstringstringwithstring:@ " "],@" c Nil]; Nsarray *deepcopyarray=[[nsarray alloc] Initwitharray:array Copyitems:yes]; Nsarray * truedeepcopyarray = [Nskeyedunarchiver unarchiveobjectwithdata: [ Nskeyedarchiver Archiveddatawithrootobject:array]];
Truedeepcopyarray is a deep copy of the full sense, while Deepcopyarray is not, for the immutable elements within the Deepcopyarray it is the pointer copy. Or our own way of implementing deep copies. Because if an element of the container is immutable, the object remains unchanged after you copy it, so you only need to copy the pointer. The pointer copy is sufficient unless you re-assign the elements inside the container. For example, [[Array objectatindex:0]appendstring:@ ' SD '] other objects in the container will not be affected. [[Array objectatindex:1] and [[Deepcopyarray objectatindex:0] even point to the same block of memory, but we have no way to modify it-because it is immutable. So the pointer copy is sufficient. So this is not a deep copy of the full meaning, but Apple's official document has listed it as deeply copy, and has added a copy and mutablity relationship description, so do a note here (there is a little doubt, there is understanding of the enlighten AH).
Or our own way of implementing deep copies (slightly).
3. Custom Objects
If it is the object we define, then we have to implement nscopying,nsmutablecopying ourselves so that we can invoke copy and Mutablecopy. As an example:
@interfaceMyobj:nsobject<nscopying,nsmutablecopying>{nsmutablestring*name; NSString*Imutablestr; intAge ;} @property (nonatomic, retain) nsmutablestring*Name: @property (nonatomic, retain) nsstring*Imutablestr, @property (nonatomic)intAge ;@end@implementationMYOBJ@synthesizename;@synthesizeAge ;@synthesizeImutablestr;- (ID) init{if(self =[Super Init]) {Self.name=[[Nsmutablestring alloc]init]; Self.imutablestr=[[NSString Alloc]init]; Age= -1; } returnSelf ;}- (void) dealloc{[name release]; [Imutablestr release]; [Super Dealloc];}- (ID) Copywithzone: (Nszone *) zone{MYOBJ*copy = [[Selfclass] [allocwithzone:zone] init]; Copy->name =[name copy]; Copy->imutablestr =[imutablestr copy];//copy->name = [name Copywithzone:zone];;//copy->imutablestr = [name Copywithzone:zone];//Copy->age =Age ; returncopy;}- (ID) Mutablecopywithzone: (Nszone *) zone{MYOBJ*copy = Nscopyobject (self,0, zone); Copy->name =[Self.name mutablecopy]; Copy->age =Age ; returncopy;}
IOS: Deep copy and shallow copy