美文网首页
runtime - 实现对象的copy/mutablecopy

runtime - 实现对象的copy/mutablecopy

作者: 青春未过 | 来源:发表于2018-01-06 23:13 被阅读97次

    在我们开发过程中,有时会遇到对象进行拷贝的情况,在对象属性少的情况下,我们可以直接在 copyWithZone:/mutableCopyWithZone: 方法里手动对复制后的对象的相应属性赋值,但在属性成员很多的情况及通过runtime在运行时关联属性时,我们这种手动赋值的方式就有点应付不过来了。不过不用担心,OC有runtime这把利器,让一切变得是那么简单。废话不多说,用代码说话。

    1. 为对象增加一个扩展并遵守 <NSCopying,NSMutableCopying>协议

      #import <objc/runtime.h>
      @interface Person()<NSCopying,NSMutableCopying>
      @end
      
    2. 实现协议

      -(id)copyWithZone:(NSZone * )zone{
          id objCopy = [[[self class] allocWithZone:zone] init];
          // 1.获取属性列表
          unsigned int propertyCount = 0;
          objc_property_t * propertyArray = class_copyPropertyList([self class], &propertyCount);
          
          for (int i=0; i<propertyCount; i++) {
              
              objc_property_t  property = propertyArray[i];
              
              // 2.属性名字
              const char * propertyName = property_getName(property);
              NSString * key = [NSString stringWithUTF8String:propertyName];
              
              // 3.通过属性名拿到属性值
              id value=[self valueForKey:key];
              NSLog(@"name:%s,value:%@",propertyName,value);
              
              // 4.判断 值对象是否响应copyWithZone
              if ([value respondsToSelector:@selector(copyWithZone:)]) {
                  //5. 设置属性值
                  [objCopy setValue:[value copy] forKey:key];
              }else{
                  [objCopy setValue:value forKey:key];
              }
          }
          //*****切记需要手动释放
          free(propertyArray);
          return objCopy;
      }
      
      -(id)mutableCopyWithZone:(NSZone *)zone{
          id objcopy = [[[self class]allocWithZone:zone] init];
          //    1.获取属性列表
          unsigned int count = 0;
          objc_property_t* propertylist = class_copyPropertyList([self class], &count);
          
          for (int i = 0; i < count ; i++) {
              objc_property_t property = propertylist[i];
              //    2.获取属性名
              const char * propertyName = property_getName(property);
              NSString * key = [NSString stringWithUTF8String:propertyName];
              //    3.获取属性值
              id value = [self valueForKey:key];
              //    4.判断属性值对象是否遵守NSMutableCopying协议
              if ([value respondsToSelector:@selector(mutableCopyWithZone:)]) {
                  //    5.设置对象属性值
                  [objcopy setValue:[value mutableCopy] forKey:key];
              }else{
                  [objcopy setValue:value forKey:key];
              }
          }
          //*****切记需要手动释放
          free(propertylist);
          return objcopy;
      
      }
      

    通过以上两个方法的实现,可以应付对象的拷贝场景。

    小结下:
    使用runtime机制实现对象的拷贝有以下几个步骤:
    1. 导入<objc/runtime.h>头文件
    2. 遵守<NSCopying,NSMutableCopying>协议
    3. 实现mutableCopyWithZone:/copyWithZone:方法
    4. 获取类的属性列表
    5. 对属性列表进行遍历
    5.1 拿到属性
    5.2 拿到属性名
    5.3 通过属性名拿到属性值, 使用valueForKey:方法
    5.4 判断值对象是否响应协议方法,将值赋值给新对象的相应属性
    6.释放属性指针

    相关文章

      网友评论

          本文标题:runtime - 实现对象的copy/mutablecopy

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