Objective-c talk about the deep copy, copy and mutable copy are not completely copied

Source: Internet
Author: User
(1) Pointer assignment in string, copy and mutablecopy

   NSString and NSString

(1) Pointer assignment

    Must point to the same string address.

   (2) copy (same as direct pointing)

    NSString * [email protected] "aaa";
    NSString * str2 = [str1 copy];
    NSLog (@ "str1:% p ---- str2:% p", & str1, & str2); // Pointer address output, not the same, indicating that the pointer is newly created
    NSLog (@ "str1:% p ---- str2:% p", str1, str2); // Pointer points to the content address output, it is the same, indicating that the content has not been copied
      The results show that Copy did not implement copying, indicating that the following cases are equivalent and all point to the same memory area

NSString * str2 = str1;
NSString * str3 = [[NSString alloc] initWithString: str1];
NSString * str4 = [NSString stringWithString: str1];
   NSString * str5 = [str1 copy];
      If the scene requires, for example, to destroy a place pointed to by str1, you must first copy to a new address, and then use str2 to copy the NSString.

   (3) mutablecopy (implemented copy)

    NSString * [email protected] "aaa";
    NSString * str2 = [str1 mutableCopy];
    NSLog (@ "str1:% p ---- str2:% p", & str1, & str2); // Pointer address output, not the same, indicating that the pointer is newly created
    NSLog (@ "str1:% p ---- str2:% p", str1, str2); // The pointer points to the content address output, which is different, indicating that the memory is reopened, and the content of str1 is copied to the new memory , The str2 variable points to this new address
 

   NSMutableString to NSMutableString

      (1) Pointer assignment:

       Must point to the same variable string address.

       (2) mutablecopy

    NSMutableString * mStr = [NSMutableString stringWithString: @ "abc"];
    NSMutableString * mStr2 = [mStr mutableCopy];
    NSLog (@ "mstr:% p ----- mstr2:% p", mStr, mStr2); // The pointer content address is different, indicating that the copy is implemented
    [mStr2 appendString: @ "def"];
    NSLog (@ "mstr:% @ ----- mstr2:% @", mStr, mStr2); // Not related to each other
 In this way, a copy of NSMutableString is realized, and two independent variable strings are generated.

        (3) copy (error, will collapse)

    NSMutableString * mStr2 = [mStr copy];
   

    NSMutableString to NSString

   (1) Pointer assignment:

    NSMutableString * mStr = [NSMutableString stringWithString: @ "abc"];
    NSString * str = mStr;
    NSLog (@ "mstr:% p ----- str:% p", mStr, str); // The pointer points to the same content address, indicating that the change of mStr will link str
    [mStr appendString: @ "def"];
    NSLog (@ "mstr:% @ ----- str:% @", mStr, str); // The change of mStr affected str
 In this case, the change of mStr will affect str, but the change of str will be redirected, and will not affect mStr

   (2) Copy and mutablecopy:

    NSMutableString * mStr = [NSMutableString stringWithString: @ "abc"];
    NSString * str = [mStr copy]; // NSString * str = [mStr mutableCopy]; can also be achieved
    NSLog (@ "mstr:% p ----- str:% p", mStr, str);
In this case, str copies mStr, and the change of mStr does not affect str.

But in this, [mStr copy] and [mstr mutableCopy], although both copy the original mStr and open up a new memory area, the difference is that the object copied by the former is immutable, and the latter is mutable. The assignment of variable strings to NSString actually loses its dynamicity.

 

    NSString to NSMutableString

    Using copy method, let NSString assign value to NSMutableString is also a dead act, you should use StringWithString method to initialize NSMutableString

    NSString * [email protected] "str1";
    NSMutableString * mStr = [str1 copy];
    [mStr appendFormat: @ "abc"];
 

  

in conclusion:

1. Between NSString, copy can not achieve copy (equivalent direct pointing), must be mutablecopy to achieve copy

2. Between NSMutableString, Mutablecopy realizes copying.

3. For NSMutableString copy to NSString, both copy and mutablecopy can complete the task.

So: For copying between strings, Mutablecopy must be used to achieve copying.

 

Direct assignment of array variable assignment, copy and mutablecopy

     NSArray and NSArray

   (1) Direct pointing

    It must point to the same array.

   (2) copy

    NSArray * array1 = [NSArray arrayWithObjects: @ "1", @ "2", @ "3", nil];
    NSArray * array2 = [array1 copy];
    NSLog (@ "arr1:% p, arr2:% p", & array1, & array2); // The pointer addresses are different, indicating that they are two different pointer variables
    NSLog (@ "arr1:% p, arr2:% p", array1, array2); // The array pointer points to the same content, indicating that the copy method is still directly pointed to NSArray, no copy
    NSLog (@ "arr1:% p, arr2:% p", array1 [0], array2 [0]); // The array address is the same, the content address must be the same
    Explain that copy does not implement copy, and still points to the same array.

     (3) mutablecopy

    NSArray * array1 = [NSArray arrayWithObjects: @ "1", @ "2", @ "3", nil];
    NSArray * array2 = [array1 mutableCopy];
    NSLog (@ "arr1:% p, arr2:% p", & array1, & array2); // Different pointer variables, different addresses
    NSLog (@ "arr1:% p, arr2:% p", array1, array2); // The array address is different, indicating that the array is copied
    NSLog (@ "arr1:% p, arr2:% p", array1 [0], array2 [0]); // The element address is the same, indicating that the element has not been copied
     It means that the copy is realized, but the pointer of the element in the array is copied, but the element is not copied.

 

   NSMutableArray and NSMutableArray

    (1) Direct pointing

      The same thing. It must be changed together.

    (2) mutablecopy

    NSMutableArray * mArray1 = [NSMutableArray arrayWithObjects:
                             [NSMutableString stringWithString: @ "1"],
                             [NSMutableString stringWithString: @ "2"],
                             [NSMutableString stringWithString: @ "3"], nil];
    NSMutableArray * mArray2 = [mArray1 mutableCopy];
    NSLog (@ "arr1:% p, arr2:% p", & mArray1, & mArray2); // The pointer addresses are different, indicating that they are two different pointers
    NSLog (@ "arr1:% p, arr2:% p", mArray1, mArray2); // The array address is different, indicating that the array has been copied
    NSLog (@ "arr1:% p, arr2:% p", mArray1 [0], mArray2 [0]); // The content address is the same, indicating that the content is not copied
      Explain that mutablecopy implements copying, but does not implement copying of internal elements of the array.

      In the case where this content is a variable element, if the variable array 1 element is changed, the variable array 2 element will also be changed together. There is no complete copy. To achieve a full copy, we must continue to peel apart layers, all copies and then reorganize the array.

 

      Description:

      1. Like NSString, the copy method of NSArray does not actually implement a little copy (same as direct pointing), only Mutablecopy can achieve copy.

      2. But mutablecopy only copies the array itself and the pointer of each element in the array, and does not implement the copying of array elements.

 

        

Custom class implements NSCopying and NSMutableCopying protocols

If these two protocols are not implemented, neither the copy nor mutablecopy methods will get a response, and the degree of specific copying also depends on the specific implementation

New Student class

.h

#import <Foundation / Foundation.h>

@interface Student: NSObject <NSCopying, NSMutableCopying>

@property (copy) NSString * name;
@property (copy) NSString * age;
@property (strong) NSMutableArray * GradeArray;
@end
 .m

#import "Student.h"

@implementation Student

-(id) initWithName: (NSString *) name GradeArray: (NSMutableArray *) gradeArray {
    self = [super init];
    if (self) {
        self.name = name;
        self.GradeArray = gradeArray;
    }
    return self;
}

-(id) copyWithZone: (NSZone *) zone
{
    Student * stu = [[Student allocWithZone: zone] initWithName: self.name GradeArray: self.GradeArray];
    return stu;
}

-(id) mutableCopyWithZone: (NSZone *) zone {
    Student * stu = [[Student allocWithZone: zone] initWithName: self.name GradeArray: self.GradeArray];
    return stu;
}

@end
 

copy:

    Student * stu1 = [[Student alloc] init];
    [email protected] "stu1";
    stu1.GradeArray = [[NSMutableArray alloc] init];
    [stu1.GradeArray addObject: @ "100"];
    Student * stu2 = [stu1 mutableCopy];
    NSLog (@ "stu1:% p ---- stu2:% p", stu1, stu2); // stu1: 0x7faa43c1b050 ---- stu2: 0x7faa43c1d0d0
    NSLog (@ "stu1:% p ---- stu2:% p", stu1.name, stu2.name); // stu1: 0x10df5f080 ---- stu2: 0x10df5f080
    NSLog (@ "stu1:% p ---- stu2:% p", stu1.GradeArray, stu2.GradeArray); // stu1: 0x7faa43c1ad40 ---- stu2: 0x7faa43c1ad40
It means that the object is copied, but the content pointed by the member's pointer is not copied.

For custom objects, the deepest copy can only be to the extent of copying the member pointer, indicating that neither copy nor mutablecopy is a complete copy

 

To sum up, if you want to achieve a complete copy of an object:

1. Mutablecopy must be performed on each object in Class separately (for basic data objects, copy is not necessarily OK)

2. And if there are objects of container nature (such as Array and MutableArray) in Class, currently only the array is copied, and the contents of the elements in the variable array are not copied. You must fully copy and dig deeper. Mutablecopy of each element

It is not a complete copy until an object that does not exist in a container is mutablecopyed

    Student * stu1 = [[Student alloc] init];
    [email protected] "stu1";
    stu1.GradeArray = [[NSMutableArray alloc] init];
    [stu1.GradeArray addObject: @ "100"];
    Student * stu2 = [stu1 mutableCopy];
    stu2.name = [stu1.name mutableCopy];
    stu2.GradeArray = [stu1.GradeArray mutableCopy];
    NSLog (@ "stu1:% p ---- stu2:% p", stu1, stu2); // stu1: 0x7faa43c1b050 ---- stu2: 0x7faa43c1d0d0
    NSLog (@ "stu1:% p ---- stu2:% p", stu1.name, stu2.name); // stu1: 0x10df5f080 ---- stu2: 0x10df5f080
    NSLog (@ "stu1:% p ---- stu2:% p", stu1.GradeArray, stu2.GradeArray); // stu1: 0x7faa43c1ad40 ---- stu2: 0x7faa43c1ad40
 So a better way is to archive first and then unpack as stated in the last blog

    NSData * data = [NSKeyedArchiver archivedDataWithRootObject: stu1];
    Student * stu2 = [NSKeyedUnarchiver unarchiveObjectWithData: data];
 Ah completely copied ~~ everything is clean. . .

Objective-C talk about shallow copy, neither copy nor mutable copy are full copies

Related Article

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.