Deep copy and shallow copy of iOS development (mutablecopy and copy)

Source: Internet
Author: User

Before reading this article, we first understand the difference between copy and retain, if there is an incorrect place, we would like to advise you:

The difference between copy and retain:

copy is to create a new object, retain is to create a pointer, 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 represents two objects The same address (creating a pointer, copy of the pointer), the content of course the same, the object's retain value +1 that is, retain is a pointer copy and copy is a copy of the content.

Of course not all objects in iOS support Copy,mutablecopy, classes that comply with the Nscopying protocol can send a copy message, classes that adhere to 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";
nsstring *stringcopy = [string copy];
nsmutablestring *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 = [string copy];
nsmutablestring *mstringcopy = [string copy];
nsmutablestring *stringmcopy = [string mutablecopy];
[mstringcopy appendstring:@ "MM"];//error
[String appendstring:@ "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 object
Nsarray *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 pointer
NSLog (@ "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 copy (shallow copy), while MArrayCopy1 is Object copy (deep copy), 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
//do a test
nsmutablestring *teststring = [MArray1 objectatindex:0];
//teststring = @ "1a1";//This will change the teststring pointer, in fact, the @ "1a1" temporary object is assigned to TestString
[teststring appendstring:@ "tail"];//so that 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:@ "First"],[ nsstringstringwithstring:@ "B"],@ "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:
@interface myobj:nsobject<nscopying,nsmutablecopying>
{
nsmutablestring *name;
nsstring *imutablestr;
int age;
}
@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
{
if (self = [super init])
         {
self.name = [[nsmutablestring alloc]init];
self.imutablestr = [[NSString alloc]init];
Age =-1;
         }
return self;
}
-(void) Dealloc
{
[name release];
[Imutablestr release];
[Super Dealloc];
}
-(ID) Copywithzone: (Nszone *) Zone
{
MYOBJ *copy = [[[Self class] allocwithzone:zone] init];
copy->name = [name copy];
copy->imutablestr = [imutablestr copy];
//Copy->name = [name Copywithzone:zone];;
//copy->imutablestr = [name copywithzone:zone];//
copy->age = age;
return copy;
}
-(ID) Mutablecopywithzone: (Nszone *) Zone
{
MyObj *copy = nscopyobject (self, 0, zone);
copy->name = [Self.name mutablecopy];
copy->age = age;
return copy;
}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.