The purpose of the copy design: the original object will not be affected when the copy is changed.
1. a copy of an object can be created using the copy or mutablecopy method.
2. Copy needs to implement the nscopying protocol first, and the created copy cannot be changed (nsstring, nsarray, nsdictionary)
Mutablecopy requires the nsmutablecopying protocol to be created first. It creates a mutable copy (such as nsmutablestring, nsmutablearray, and nsmutabledictionary)
3. Deep replication: the source object and copy point to the same object. The Reference Counter of the source object remains unchanged, and the copy counter is set to 1.
Light replication: pointer replication. The source object and the copy object point to the same 20 objects. The reference object of the object is added with 1, which is equivalent to a retain operation.
Only the immutable object that creates an immutable copy is the shortest copy, and the others are all deep copies.
4. By default, three OC objects, nsstring, nsarray, and nsdictionary, have implemented cooppying and nsmutablecopying protocols.
5. Add a copy function for a custom class:
To customize copy, follow nscopying and implement copywithzone: Method
To customize mutablecopy, you must comply with nsmutablecopying and implement mutablecopyzone: Method
For example, copy:
We recommend that you replace the class name with self class.
-(ID) copywithzone :( nszone *) Zone {
ID copy = [[[self class] allocwithzone: Zone] init];
// Initialize some attributes here
Return copy;
}
The test DEMO code is as follows:
This demo mainly demonstrates copy and mutablecopy, which describe deep copy and shallow copy.
And custom copy and mutablecopy Methods
Student. h file
# Import <Foundation/Foundation. h>
@ Interface Student: nsobject <nscopying>
// Copy indicates that the set method will release the old object and copy the new object.
// Modifying external variables does not affect internal member variables
// Suggestion: Generally, the copy policy is used for nsstring and retain is used for other objects.
// The retain and the outside are the same object, and the name attribute will be changed.
@ Property (nonatomic, retain) nsstring * Name;
+ (ID) studentwithname :( nsstring *) Name;
@ End
Student. M file:
# Import "student. H"
@ Implementation student
/**
// @ Property (copy): It means the following setname method.
-(Void) setname :( nsstring *) name {
If (_ name! = Name ){
[_ Name release];
_ Name = [Name copy];
}
}
**/
+ (ID) studentwithname :( nsstring *) name {
// It is best to write slef class
Student * Stu = [[[self class] alloc] init] autorelease];
Stu. Name = Name;
Return Stu;
}
# Pragma mark coping protocol Method
// The copy object created here is not required to be released
-(ID) copywithzone :( nszone *) Zone {
Student * Copy = [[self class] allocwithzone: Zone] init];
Copy. Name = self. Name;
Return copy;
}
// Description cannot print self internally. Otherwise, there will be an endless loop.
-(Nsstring *) Description {
Return [nsstring stringwithformat: @ "name = % @", _ name];
}
-(Void) dealloc {
Nslog (@ "Student % @ is destoryed", self );
[_ Name release];
[Super dealloc];
}
@ End
Goodstudent. h file:
# Import "student. H"
@ Interface goodstudent: Student
@ Property (nonatomic, assign) int age;
+ (ID) goodstudentwithage :( INT) Age name :( nsstring *) Name;
@ End
Goodstudent. M file:
# Import "goodstudent. H"
@ Implementation goodstudent
+ (ID) goodstudentwithage :( INT) Age name :( nsstring *) name {
Goodstudent * Good = [goodstudent studentwithname: Name];
Good. Age = age;
Return good;
}
# Pragma mark override the parent class Method
-(ID) copywithzone :( nszone *) Zone {
// You must call this method of the parent class because the parent class helped us copy the name.
Goodstudent * Copy = [Super copywithzone: Zone];
Copy. Age = self. Age;
Return copy;
}
-(Nsstring *) Description {
Return [nsstring stringwithformat: @ "[name = % @, age = % I]", self. Name, _ age];
}
@ End
Main Test method:
# Import <Foundation/Foundation. h>
# Import "student. H"
# Import "goodstudent. H"
Void stringmutablecopy (){
Nsstring * string = [[nsstring alloc] initwithformat: @ "Age is % I", 10];
// Generate a new object. The counter is 1, and the counter of the source object does not change.
Nsmutablestring * STR = [String mutablecopy];
Nslog (@ "string: % zi", [String retaincount]); // 1
Nslog (@ "str: % zi", [STR retaincount]); // 1
// STR and string are not the same object
Nslog (@ "% I", STR = string); // 0
[STR release];
[String release];
}
/**
Only in this case is the shortest copy: the pointer copy does not produce new objects.
**/
Void stringcopy (){
Nsstring * string = [[nsstring alloc] initwithformat: @ "Age is % I", 10];
// Copy is an immutable copy. Because the source object itself is immutable, copy directly returns the source object itself for the sake of performance.
// Source object counter + 1
Nsstring * STR = [String Copy];
Nslog (@ "% zi", [String retaincount]); // 2
Nslog (@ "% zi", [STR retaincount]); // 2
// Same object
Nslog (@ "% I", STR = string); // 1
[STR release];
[String release];
}
/**
There is only one case: String-string
**/
// Deep copy
Void mutablestringcopy (){
Nsmutablestring * string = [nsmutablestring stringwithformat: @ "Age is % I", 10];
Nsstring * STR = [String Copy];
Nslog (@ "% I", STR = string); // 0
}
// Deep copy
Void mutablestringmutablecopy (){
Nsmutablestring * string = [nsmutablestring stringwithformat: @ "Age is % I", 10];
Nsmutablestring * STR = [String mutablecopy];
Nslog (@ "% I", STR = string); // 0
[STR appendstring: @ "ABC"];
Nslog (@ "% @", STR); // 10abc
}
// Copy of The stendent attribute
Void studentnamecopy (){
Student * Stu = [[STUDENT alloc] init] autorelease];
Nsmutablestring * string = [nsmutablestring stringwithformat: @ "Age is % I", 10];
Stu. Name = string;
[String appendstring: @ "ABCD"];
Nslog (@ "Stu. Name = % @", Stu. Name );
Nslog (@ "string = % @", string );
}
// Copy of The stendent object
Void studentcopy (){
Student * stu1 = [STUDENT studentwithname: @ "stu1"];
Student * stu2 = [stu1 copy];
Nslog (@ "stu1: % @", stu1.name );
Nslog (@ "stu2: % @", stu2.name );
Stu2.name = @ "stu2 ";
Nslog (@ "stu1: % @", stu1.name );
Nslog (@ "stu2: % @", stu2.name );
Nslog (@ "% I", stu1 = stu2 );
[Stu2 release];
}
// Copy of The goodstudent subclass
Void goodstudent (){
Goodstudent * goodstu1 = [goodstudent goodstudentwithage: 20 name: @ "goodstu1"];
Nslog (@ "goodstu1: % @", goodstu1 );
Goodstudent * goodstu2 = [goodstu1 copy];
Nslog (@ "goodstu2: % @", goodstu2 );
}
Int main (INT argc, const char * argv [])
{
@ Autoreleasepool {
Nslog (@ "---- stringmutablecopy ----");
Stringmutablecopy ();
Nslog (@ "---- stringcopy ----");
Stringcopy ();
Nslog (@ "---- mutablestringcopy ----");
Mutablestringcopy ();
Nslog (@ "---- mutablestringmutablecopy ----");
Mutablestringmutablecopy ();
Nslog (@ "---- studentnamecopy ----");
Studentnamecopy ();
Nslog (@ "---- studentcopy ----");
Studentcopy ();
Nslog (@ "---- goodstudent ----");
Goodstudent ();
}
Return 0;
}