Replication of objects in OC: II

Posted by onepixel on Tue, 21 Dec 2021 11:18:54 +0100

Ladies and gentlemen, we introduced object replication in OC in the previous chapter, and we will continue to introduce this knowledge in this chapter.
In the last chapter, we introduced what replication is and how to replicate. This chapter will introduce the principles behind replication and the principles of replication operation.

Principle of replication

When we copy through the two methods of copy operation (copy and mutableCopy), we essentially call the two methods' copyWithZone 'and' mutableCopyWithZone ' These two methods are the methods in the 'NSCopying' and 'NSMutableCopying' protocols, and the NSObject class implements these two protocols and overrides these two methods in the protocol. Therefore, we can implement the copy operation by overriding these two methods in our own defined class. If you copy without overriding these two methods, an exception will occur at run time. The following is sample code for rewriting the method.
 

-(id) copyWithZone:(NSZone *)zone
{
    NSLog(@"copying");
    //Assign values to each attribute
}

-(id) mutableCopyWithZone:(NSZone *)zone
{
    NSLog(@"mutable copying");
    //Assign values to each attribute
}

For the classes in OC and the classes provided in the Foundation framework, we can directly use the copy method to implement the copy operation, because these classes have overridden the 'copyWithZone' and 'mutableCopyWithZone' methods.

Principle of replication


There are two main principles here. On the one hand, it refers to deep and shallow replication, and on the other hand, it refers to whether the newly copied object can be modified.

  1. For custom classes, our principle is to use deep copy, and the copied new objects can be modified. That is to say, whether the copy method or mutableCopy method is used, the copy operation is a deep copy, and the copied objects can be modified.
  2. For classes in OC, if the class object is immutable (such as NSString), the copy method is shallow copy, and the copied object cannot be modified. mutableCopy method is deep copy, and the copied objects can be modified.
  3. For classes in OC, if the objects of the class are variable (such as NSMutableString), the copy method and mutableCopy method are deep copy, and the copied objects can be modified.


For the assignment operation using the equal sign, it is equivalent to shallow copy. No matter whether the copied object is variable or not, it just copies a reference and does not create a new object.

For user-defined classes, you need to follow the principles just mentioned when implementing copy methods in user-defined classes. For classes in OC, the methods of copy operation have been implemented. We can verify the principles of these methods through code. The following is an example code, please refer to:
 

#include <Foundation/Foundation.h>

@interface Book : NSObject
    @property (nonatomic,readwrite,strong) NSString *name;
    @property (nonatomic,readwrite,strong) NSMutableString *group;
    @property (nonatomic,readwrite,copy) Book* test;
    @property (nonatomic,readwrite) int price;

    -(void) show;
@end

@implementation Book
    @synthesize name;
    @synthesize price;
    @synthesize group;
    @synthesize test;

    -(void) show
    {
        NSLog(@"----Book Inof----");
        NSLog(@"name: %@ -- %p",name,name);
        NSLog(@"group: %@ -- %p",group,group);
        NSLog(@"test: %@ -- %p",test,test);
        NSLog(@"price: %d" ,price);
        NSLog(@"-----------------");
    }

//Define the copy method yourself. The principle is deep copy. Deep copy using mutableCopy method
-(id) copyWithZone:(NSZone *)zone
{
    NSLog(@"copying");
    Book *obj = [[[self class] allocWithZone:zone] init];

    obj.name = [self.name mutableCopy];
    obj.group = [self.group mutableCopy];
    obj.test = [self.test mutableCopy];
    obj.price = self.price;

    return obj;
}


-(id) mutableCopyWithZone:(NSZone *)zone
{
    NSLog(@"mutable copying");
    //Direct use of the copy principle of intersection
    // id obj = [super mutableCopy];

    //Use your copy principle directly
    id obj = [self copy];

    return obj;
}

@end

int main()
{
    NSString *str1 = @"abc";
    NSString *str2 = [str1 copy];
    NSString *str3 = [str1 mutableCopy];

    //NSString object, the copy method performs shallow copy, and the mutableCopy method performs deep copy
    NSLog(@"string1 : %@ -- %p",str1,str1);
    NSLog(@"string2 : %@ -- %p",str2,str2);
    NSLog(@"string3 : %@ -- %p",str3,str3);

    NSArray *arr1 = [NSArray arrayWithObjects:@"aa",@"bb",@"cc",nil];
    NSArray *arr2 = [arr1 copy];
    NSArray *arr3 = [arr1 mutableCopy];

    //For immutable objects such as NSArray, the copy method performs shallow copy and the mutableCopy method performs deep copy
    NSLog(@"array1: %@ -- %p",arr1,arr1);
    NSLog(@"array2: %@ -- %p",arr2,arr2);
    NSLog(@"array3: %@ -- %p",arr3,arr3);

    NSMutableArray *mutArr1 = [NSMutableArray arrayWithObjects:@"aa",@"bb",@"cc",nil];
    NSMutableArray *mutArr2 = [mutArr1 copy];
    NSMutableArray *mutArr3 = [mutArr1 mutableCopy];

    //For mutable objects such as NSMutableArray, both the copy method and mutableCopy method perform deep copy
    NSLog(@"mutabArray1: %@ -- %p",mutArr1,mutArr1);
    NSLog(@"mutabArray2: %@ -- %p",mutArr2,mutArr2);
    NSLog(@"mutabArray3: %@ -- %p",mutArr3,mutArr3);


    Book *b1 = [[Book alloc] init];
    [b1 setName:@"book1"];
    [b1 setPrice:1];
    [b1 setGroup:@"group1"];
    NSLog(@"Book1 --->");
    [b1 show];
    NSLog(@"Address: %p",b1);

    Book *b2 = [[Book alloc] init];
    //When set to the copy property, the copy method of the class will be called
    [b2 setTest:b1];
    NSLog(@"Book2 --->");
    [b2 show];
}


The example code demonstrates how the custom class implements the copy operation by overriding the copy and mutalbeCopy methods At the same time, it also demonstrates the replication principles of classes in OC by printing the object address. We have added notes in relevant places, but we still hope you can practice it yourself, so as to deepen your understanding of these replication principles.


Finally, we summarize the contents of this chapter:

  • 1. The copy operation surface is implemented using the i`copy 'and' mutableCopy 'methods, but it is essentially implemented through the two methods of' copyWithZone 'and' mutableCopyWithZone ';
  • 2. The two methods' copyWithZone 'and' mutableCopyWithZone 'need to be implemented in the user-defined class, otherwise runtime exceptions will be raised when copying;
  • 3. The classes provided in OC have implemented the 'copyWithZone' and 'mutableCopyWithZone' methods. We can copy them directly;
  • 4. We need to understand the replication principles of OC provided classes and follow the replication principles of user-defined classes when customizing classes;

Ladies and gentlemen, that's all for the content of this chapter. If you want to know what will happen next, let's listen to the next chapter!

Topics: iOS objective-c