SoFunction
Updated on 2025-04-09

Assignment and object copy in IOS ObjectiveC

Assignment and object copy in IOS ObjectiveC

During the development process, we often encounter the problem of object copying. Below we discuss the difference between assignment operations, object copying, and shallow copy and deep copying and their respective implementation methods.

1. Assignment operations for different objects

There are two types of objects in Objective-C, one is a structure (or basic data type is also counted), and the other is an NSObject object.

For structures, the code will operate directly on the body, so the assignment operation will create a copy of the source object (a new object); while for NSObject objects, a pointer must be used to operate the object, so its assignment operation is equivalent to copying a pointer rather than an object, that is, the assignment operation makes both the source pointer and the new pointer point to the same NSObject object. This is a bit difficult to understand, please see the following code:

//  
 
#import <Foundation/> 
 
@interface TestObject : NSObject 
{ 
  @public 
  int x; 
  int y; 
} 
@end 
 
@implementation TestObject 
@end 
 
typedef struct TestStruct 
{ 
  int x; 
  int y; 
} 
TestStruct; 
 
int main(int argc, const char * argv[]) 
{ 
 
  @autoreleasepool { 
     
    TestStruct ts1 = {100, 50}; 
    NSLog(@"ts1: %p, %d, %d", &ts1, , ); 
     
    TestStruct ts2 = ts1; 
    NSLog(@"ts2: %p, %d, %d", &ts2, , ); 
 
    TestObject* to1 = [[[TestObject alloc] init] autorelease]; 
    NSLog(@"to1: %p, %d, %d", to1, to1->x, to1->y); 
     
    TestObject* to2 = to1; 
    NSLog(@"to2: %p, %d, %d", to2, to2->x, to2->y); 
     
  } 
  return 0; 
} 

The running results of the program are as follows:

ts1: 0x7fff63463898, 100, 50 
ts2: 0x7fff63463890, 100, 50 
to1: 0x7fc342d00370, 0, 0 
to2: 0x7fc342d00370, 0, 0 

The program code first defines a class TestObject (inherited from NSObject), and then defines a structure TestStruct. Both contain two integer member variables x and y. Then in the main function, the program first allocates memory space for TestStruct structure ts1 and assigns initial values ​​to its member variables, x is 100 and y is 50. Then, the address and member variables of the structure are printed out through the NSLog function, that is, the content of the output first line. Next, the program executes the assignment statement, assigning ts1 to another TestStruct structure object ts2. This statement will allocate another piece of memory for ts2, and then copy the values ​​of each member variable of ts1 over. It can also be seen from the output of the second line that the address is different, so if you modify the value of the member variable of ts1, it will not affect ts2.

Let’s take a look at TestObject. The program then allocates a new memory space using the alloc static method, and then initializes it through the init instance method (the value of all member variables is 0), and finally returns the first address of the memory space. The essence of to1 is a pointer pointing to the created TestObject object. Next, the program assigns to1 to to2. to2 is also a pointer to the TestObject object, with the same value as to1, that is, both point to the same object. So in this case, the modification to to1 will affect to2 at the same time.

2. Object copy

The NSObject class of the Foundation framework provides two methods, namely the copy and mutableCopy methods, which are used to copy NSObject objects. The copy method will call the copyWithZone: method of the NSCopying protocol, and mutableCopy will call the mutableCopyWithZone: method of the NSMutableCopying protocol. Modify the above code as follows:

#import &lt;Foundation/&gt; 
 
@interface TestObject : NSObject 
{ 
  @public 
  int x; 
  int y; 
} 
@end 
 
@implementation TestObject 
- (NSString*)description 
{ 
  return [NSString stringWithFormat:@"%@: %p, x: %d, y: %d", [self class], self, x, y]; 
} 
@end 
 
typedef struct TestStruct 
{ 
  int x; 
  int y; 
} 
TestStruct; 
 
int main(int argc, const char * argv[]) 
{ 
  @autoreleasepool 
  {     
    TestObject* to1 = [[[TestObject alloc] init] autorelease]; 
    to1-&gt;x = 100; to1-&gt;y = 50; 
    TestObject* to2 = [[[TestObject alloc] init] autorelease]; 
    to2-&gt;x = 200; to2-&gt;y = 400; 
    TestObject* to3 = [[[TestObject alloc] init] autorelease]; 
    to3-&gt;x = 300; to3-&gt;y = 500; 
     
    //Create an array1 containing to1, to2, to3    NSArray* array1 = [NSArray arrayWithObjects:to1, to2, to3, nil]; 
    NSLog(@"array1: %p, \n%@", array1, array1); 
     
    //array2 is the result of array1 calling copy    NSArray* array2 = [array1 copy]; 
    NSLog(@"array2: %p, \n%@", array2, array2); 
    [array2 release]; 
     
    //mutableArray2 is the result of array1 calling mutableCopy    NSMutableArray* mutableArray2 = [array1 mutableCopy]; 
    NSLog(@"mutableArray2: %@, %p, \n%@", [mutableArray2 class], mutableArray2, mutableArray2); 
    [mutableArray2 removeLastObject]; 
     
    NSLog(@"After remove last object of mutableArray2"); 
     
    NSLog(@"array1: %p, \n%@", array1, array1); 
    NSLog(@"array2: %p, \n%@", array2, array2); 
    NSLog(@"mutableArray2: %p, \n%@", mutableArray2, mutableArray2); 
     
    //mutableArray3 is the result of mutableArray2 calling mutableCopy    NSMutableArray* mutableArray3 = [mutableArray2 mutableCopy]; 
    NSLog(@"mutableArray3: %p, \n%@", mutableArray3, mutableArray3); 
    [mutableArray2 release]; 
     
    //array4 is the result of mutableArray3 calling copy    NSArray* array4 = [mutableArray3 copy]; 
    NSLog(@"array4: %@, %p, \n%@", [array4 class], array4, array4); 
    [mutableArray3 release]; 
    [array4 release]; 
  } 
  return 0; 
} 

The running results of the program are as follows:

2012-03-22 19:20:49.548 ObjectCopy[18042:403] array1: 0x7f9071414820,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400", 
  "TestObject: 0x7f9071414230, x: 300, y: 500" 
) 
2012-03-22 19:20:49.550 ObjectCopy[18042:403] array2: 0x7f9071414820,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400", 
  "TestObject: 0x7f9071414230, x: 300, y: 500" 
) 
2012-03-22 19:20:49.551 ObjectCopy[18042:403] mutableArray2: __NSArrayM, 0x7f9072800000,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400", 
  "TestObject: 0x7f9071414230, x: 300, y: 500" 
) 
2012-03-22 19:20:49.552 ObjectCopy[18042:403] After remove last object of mutableArray2 
2012-03-22 19:20:49.552 ObjectCopy[18042:403] array1: 0x7f9071414820,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400", 
  "TestObject: 0x7f9071414230, x: 300, y: 500" 
) 
2012-03-22 19:20:49.553 ObjectCopy[18042:403] array2: 0x7f9071414820,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400", 
  "TestObject: 0x7f9071414230, x: 300, y: 500" 
) 
2012-03-22 19:20:49.553 ObjectCopy[18042:403] mutableArray2: 0x7f9072800000,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400" 
) 
2012-03-22 19:20:49.557 ObjectCopy[18042:403] mutableArray3: 0x7f90729000d0,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400" 
) 
2012-03-22 19:20:49.558 ObjectCopy[18042:403] array4: __NSArrayI, 0x7f9071416e70,  
( 
  "TestObject: 0x7f90714141b0, x: 100, y: 50", 
  "TestObject: 0x7f90714141c0, x: 200, y: 400" 
) 

There are several points worth noting about the operation results of the program. First, the address of array1 and array2 is the same, because the NSArray object cannot be modified after creation. Secondly, the mutableCopy method of NSArray will return an NSMutableArray object. Third, for NSArray or NSMutableArray, the mutableCopy method will create a new mutable array object, but the value of each array member is only a pointer assignment to the original array, which is a shallow copy. In contrast, it is a deep copy, that is, when copying an array, instead of copying the reference to each element of the array, it creates a new object that is the same as it.

Fourth, calling the mutableCopy method on the NSArray object returns an NSMutableArray object, while calling the copy method on the NSMutableArray object returns an NSArray object, not an NSMutableArray object.

Of course, the above discussion is about the NSArray and NSMutableArray classes in the Foundation framework. If you want to copy the objects of the class you created, you need to let the class implement the NSCopying protocol.

If you have any questions, please leave a message or go to the community of this site to exchange and discuss. Thank you for reading. I hope it can help you. Thank you for your support for this site!