美文网首页
iOS 模型数组拷贝以及model的NSCopying的runt

iOS 模型数组拷贝以及model的NSCopying的runt

作者: taisheng2017 | 来源:发表于2021-08-23 12:12 被阅读0次

    主要目的是为了记录

    问题描述:

    通常对于需要实现对模型的拷贝都需要先实现model的 NSCopying,NSMutableCopying协议。但这里存在一个问题:对于包含model(实现copy协议的)的数组使用拷贝操作,只会对数组本身进行拷贝,数组的内的model不会进行copy。

    一。实现模型数组深拷贝的方法:

     1.归档解档实现数组内部元素拷贝。
       对model使用 归档的话,model的遵循NSCoding协议且实现协议。
    
      @interface DataModel : NSObject<NSCoding,NSCopying,NSMutableCopying>
      @property (nonatomic , copy)   NSString           * title;
      @property (nonatomic , copy)   NSString           * subTitle;
      @property (nonatomic , copy)   NSString           * detail;
      @property (nonatomic , copy)   NSString           * icon;
      @property (nonatomic , assign)  float                cellHeigjt;
      @property (nonatomic , strong)  NSArray<SubModel *>*  subModelArray;
      @property (nonatomic , strong)  SubModel           * subModel;
      @end
    
       @implementation DataModel
    
        + (NSDictionary *)mj_objectClassInArray
       {
            return @{@"subModelArray":@"SubModel"};
        }
        - (id)initWithCoder: (NSCoder *)coder
         {
            if (self = [super init])
          {
             self.title = [coder decodeObjectForKey:@"title"];
             self.subTitle = [coder decodeObjectForKey:@"subTitle"];
             self.detail = [coder decodeObjectForKey:@"detail"];
             self.icon = [coder decodeObjectForKey:@"icon"];
             self.cellHeigjt = [coder decodeFloatForKey:@"cellHeigjt"];
             self.subModelArray = [coder decodeObjectForKey:@"subModelArray"];
              self.subModel = [coder decodeObjectForKey:@"subModel"];
           }
          return self;
         }
    
          - (void) encodeWithCoder: (NSCoder *)coder
        {
             [coder encodeObject:self.title forKey:@"title"];
             [coder encodeObject:self.subTitle forKey:@"subTitle"];
             [coder encodeObject:self.detail forKey:@"detail"];
             [coder encodeObject:self.icon forKey:@"icon"];
             [coder encodeFloat:self.cellHeigjt forKey:@"cellHeigjt"];
             [coder encodeObject:self.subModelArray forKey:@"subModelArray"];
            [coder encodeObject:self.subModel forKey:@"subModel"];
        }
    

    NSArray * trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData: [NSKeyedArchiver archivedDataWithRootObject:@[dataModel]]];

    所得的数组以及数组内的model都是深copy。

      2.系统方法:(推荐使用)
     - (instancetype)initWithArray:(NSArray<ObjectType> *)array copyItems:(BOOL)flag
    

    NSMutableArray * array = [NSMutableArray arrayWithArray:@[model,model1]];
    NSArray *lastArray = [[NSArray alloc]initWithArray:array copyItems:YES];
    所得的数组以及数组内的model都是深copy。

    二。结合runtime的特性以及模型数组深拷贝的方法,我们可以实现model的多层次数组模型的copy。

      @interface DataModel : NSObject<NSCopying,NSMutableCopying>
      @property (nonatomic , copy)   NSString           * title;
      @property (nonatomic , copy)   NSString           * subTitle;
      @property (nonatomic , copy)   NSString           * detail;
      @property (nonatomic , copy)   NSString           * icon;
      @property (nonatomic , assign)  float                cellHeigjt;
      @property (nonatomic , strong)  NSArray<SubModel *>*  subModelArray;
      @property (nonatomic , strong)  SubModel           * subModel;
      @end
    
       @implementation DataModel
          //##下面代码你只需要更换下model的类型,可直接复用。(在使用的地方需要导入   #import <objc/message.h>)
         -(id)copyWithZone:(NSZone *)zone{
               id objCopy = [[[self class] allocWithZone:zone] init];
                unsigned int count = 0;
                objc_property_t *properties = class_copyPropertyList([self class], &count);
                for (int i = 0; i<count; i++) {
                     objc_property_t property = properties[i];
                     const char *name = property_getName(property);
                     NSString *propertyName = [NSString stringWithUTF8String:name];
                     id value = [self valueForKey:propertyName];
                     if (value&&([value isKindOfClass:[NSMutableArray class]]||[value isKindOfClass:[NSArray class]])) {
                           id valueCopy  = [[NSArray alloc]initWithArray:value copyItems:YES];
                            [objCopy setValue:valueCopy forKey:propertyName];
                      }else if (value) {
                              [objCopy setValue:[value copy] forKey:propertyName];
                      }
                 }
                 free(properties);
                return objCopy;
             }
    
             -(id)mutableCopyWithZone:(NSZone *)zone{
                   id objCopy = [[[self class] allocWithZone:zone] init];
                  unsigned int count = 0;
                  objc_property_t *properties = class_copyPropertyList([self class], &count);
                  for (int i = 0; i<count; i++) {
                        objc_property_t property = properties[i];
                        const char *name = property_getName(property);
                         NSString *propertyName = [NSString stringWithUTF8String:name];
                         id value = [self valueForKey:propertyName];
                        if (value&&([value isKindOfClass:[NSMutableArray class]]||[value isKindOfClass:[NSArray class]])) {
                            id valueCopy  = [[NSMutableArray alloc]initWithArray:value copyItems:YES];
                            [objCopy setValue:valueCopy forKey:propertyName];
                         }else if(value){
                               [objCopy setValue:[value copy] forKey:propertyName];
                        }
                   }
                         free(properties);
                     return objCopy;
          }
         + (NSDictionary *)mj_objectClassInArray
         {
              return @{@"subModelArray":@"SubModel"};
         }
    
         @end
    
    
          @interface SubModel : NSObject<NSCopying,NSMutableCopying>
          @property (nonatomic , copy) NSString *title;
          @property (nonatomic , copy) NSString *subTitle;
          @property (nonatomic , copy) NSString *text;
          @property (nonatomic , copy) NSString *url;
          @property (nonatomic , assign) float   cellHeigjt;
          @property (nonatomic , strong)  ThridModel *thrid;
          @property (nonatomic , strong)  NSArray<ThridModel*> *thridArray;
          @property (nonatomic , strong)  NSArray<ThridModel*> *thridSubArray;
          @end
    
          @implementation SubModel
    
           +(NSDictionary *)mj_objectClassInArray
          {
             return @{@"thridArray":@"ThridModel"};
            }
    
           -(id)copyWithZone:(NSZone *)zone{
                  id objCopy = [[[self class] allocWithZone:zone] init];
                  unsigned int count = 0;
                  objc_property_t *properties = class_copyPropertyList([self class], &count);
                  for (int i = 0; i<count; i++) {
                          objc_property_t property = properties[i];
                          const char *name = property_getName(property);
                          NSString *propertyName = [NSString stringWithUTF8String:name];
                          id value = [self valueForKey:propertyName];
                          if (value&&([value isKindOfClass:[NSMutableArray class]]||[value isKindOfClass:[NSArray class]])) {
                               id valueCopy  = [[NSMutableArray alloc]initWithArray:value copyItems:YES];
                               [objCopy setValue:valueCopy forKey:propertyName];
                           }else if(value){
                               [objCopy setValue:[value copy] forKey:propertyName];
                        }
                   }
                         free(properties);
                  return objCopy;
             }
    
            -(id)mutableCopyWithZone:(NSZone *)zone{
                   id objCopy = [[[self class] allocWithZone:zone] init];
                  unsigned int count = 0;
                  objc_property_t *properties = class_copyPropertyList([self class], &count);
                  for (int i = 0; i<count; i++) {
                        objc_property_t property = properties[i];
                        const char *name = property_getName(property);
                         NSString *propertyName = [NSString stringWithUTF8String:name];
                         id value = [self valueForKey:propertyName];
                        if (value&&([value isKindOfClass:[NSMutableArray class]]||[value isKindOfClass:[NSArray class]])) {
                            id valueCopy  = [[NSMutableArray alloc]initWithArray:value copyItems:YES];
                            [objCopy setValue:valueCopy forKey:propertyName];
                         }else if(value){
                               [objCopy setValue:[value copy] forKey:propertyName];
                        }
                   }
                         free(properties);
                     return objCopy;
          }
         
       @end
    
         DataModel * dataModel = [DataModel mj_objectWithKeyValues:dict2] ;
         DataModel * copyDataModel = [dataModel  copy];
    

    到此就实现了对model的直接copy,不管model里面是否含有包含其他model的数组。拷贝后,都能得到一个全新的model。

    相关文章

      网友评论

          本文标题:iOS 模型数组拷贝以及model的NSCopying的runt

          本文链接:https://www.haomeiwen.com/subject/gwokiltx.html