About common protocols – archiving / de archiving, deep / shallow copy

Time:2021-7-30

NSCoding

Many times, we need to save our object in memory to disk to facilitate the next use of this object. Among them, this preservation process is called archive. On the contrary, turning the data in the disk into an object is called UN archive.

Unarchive includes the process of converting binary data into objects, which is called serialization; On the contrary, in the archiving process of turning an object into a file on disk, the process of turning an object into binary data is deserialized.

Or it can be understood as follows: serialization is to turn the seemingly messy binary data into an orderly structure (the objects in memory actually exist in the form of structures), and deserialization is to turn the orderly structure objects into seemingly messy binary data.

The nscoding protocol declares the methods that must be implemented by a class that can be archived and de archived. To follow this protocol, we must implement the two methods:

//Filing
- (void)encodeWithCoder:(NSCoder *)encoder
  
//De filing
- (instancetype)initWithCoder:(NSCoder *)decoder

Usually, they are implemented as follows:

//Filing
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.firstName forKey:ASCPersonFirstName];// object -> 
    [coder encodeObject:self.lastName forKey:ASCPersonLastName];
    [coder encodeFloat:self.height forKey:ASCPersonHeight];//  Float - > pay attention to the difference!
}

//De filing
- (id)initWithCoder:(NSCoder *)coder {
  self = [super init];
  if (self) {
      _firstName = [coder decodeObjectForKey:ASCPersonFirstName]; // -> object
      _lastName = [coder decodeObjectForKey:ASCPersonLastName];
      _ height = [coder decodeFloatForKey:ASCPersonHeight]; // ->  Float pay attention to the difference!
  }
  
  return self;
}

In addition, when filing and de filing are required, it is usually written as follows:

//1. Filing
MyObject *object = [MyObject new];
NSString * documentDir= [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString * archivePath = [documentDir stringByAppendingPathComponent:@"objFile"];

[NSKeyedArchiver archiveRootObject:object toFile:archivePath];    

//2. De gear
MyObject *object1 = [NSKeyedUnarchiver unarchiveObjectWithFile:archivePath];

NSCopying/NSMutableCopying

NSCopying

This protocol is mainly used to copy user-defined objects, and it is an immutable copy. There is only one method that must be implemented:

//Shallow copy / pointer copy
- (id)copyWithZone:(NSZone *)zone

If you want a custom object to get a proper copy, you have to follow this protocol and implement this method, and then the custom class object [acustominstance copy] can work correctly.

PS: when an object calls the copy method, it simply calls the copywithzone: method.

The general implementation may be:

//Case 1 - the parent class does not implement copywithzone:
@interface MyBaseObject : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, assign) NSInteger value;

- (id)copyWithZone:(NSZone *)zone {
    //MyObject *newObject = [MyObject new];// The problem with this approach is that when it is called by a subclass, there will be problems with the returned object. What we want to return is - the target object.
      MyObject *newObject = [[self class new]];//  Create an object of the target class and copy the MyObject object through the newobject pointer.
      if(newObject){
      newObject.name = _name;
        newObject.date = _date;
        newObject.value = _value;  
    }
  
    return newObject;
}

/*===========================================================================*/

//Case 2 - the parent class implements copywithzone:
@interface MySubObject : MyBaseObject
@property (nonatomic, copy)NSString *property1;
@property (nonatomic, copy)NSString *property2;
@end

- (id)copyWithZone:(NSZone *)zone {
  MySubObject *newObject = [super copyWithZone:zone];
  If (newobject) {// copy the custom attributes (instance variables) in this class.
    newObject.property1 = _property1;
    newObject.property2 = _property2;
  }
  
  return newObject;
}

When the MyObject class contains other user-defined classes, variable arrays, immutable arrays, etc., it is more complex. The implementation of this method needs to be considered according to the original intention of the class design.

NSMutableCopying

This protocol only declares one method: mutablecopywithzone:, but mutablecopy is often invoked through mutablecopy. This mutablecopy method is defined in all nsobject classes and simply calls mutablecopywithzone:.

Like the nscopying protocol, if the parent class implements the nsmutablecopying protocol, the mutablecopywithzone: method of the parent class must be called first when implementing the mutablecopywithzone: method of the child class.

Summary

I feel that the nscopying protocol is rarely used in development (cough, in fact, I have only seen some introductions in documents, written test questions or technical blogs, or common system built-in types, such as nsstring / nsmutablestring, nsarray / nsmutablearray, etc.). Therefore, it may be best to compare or refer to these existing classes or interfaces in specific actual combat.

Recommended Today

Implementation example of go operation etcd

etcdIt is an open-source, distributed key value pair data storage system, which provides shared configuration, service registration and discovery. This paper mainly introduces the installation and use of etcd. Etcdetcd introduction etcdIt is an open source and highly available distributed key value storage system developed with go language, which can be used to configure sharing […]