美文网首页
iOS如何实现自定义类的深拷贝?

iOS如何实现自定义类的深拷贝?

作者: Shaw1211 | 来源:发表于2019-05-06 23:18 被阅读0次

    遵守NSCopying协议,实现copyWithZone方法,在方法中新创建一个对象,然后对于OC和Swift来说有些区别,OC利用runtime来获取原对象的属性列表,然后通过KVC的方式给新对象进行赋值,注意需要实现setValueForUndefinedKey函数;而Swift可以通过Mirror反射,来动态获取原对象属性,然后再进行赋值操作。

    OC方式:

    CustomModel *m1 = [CustomModel new];
    m1.name = @"Shaw";
    m1.age = 27;
    CustomModel *m2 = [m1 copy];
    m2.name = @"CTT";
    m2.age = 28;
        
    NSLog(@"%@&%@", m1.name, m2.name);
    // 打印结果:Shaw&CTT
    
    @interface CustomModel : NSObject <NSCopying>
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, assign) int age;
    @end
    
    @implementation CustomModel
    
    - (id)copyWithZone:(NSZone *)zone {
        CustomModel *copy = [[[self class] alloc] init];
        unsigned int propertyCount = 0;
        objc_property_t *propertyList = class_copyPropertyList([self class], &propertyCount);
        for (int i = 0; i < propertyCount; i++ ) {
            objc_property_t thisProperty = propertyList[i];
            const char* propertyCName = property_getName(thisProperty);
            NSString *propertyName = [NSString stringWithCString:propertyCName encoding:NSUTF8StringEncoding];
            id value = [self valueForKey:propertyName];
            [copy setValue:value forKey:propertyName];
        }
        return copy;
    }
    // 注意此处需要实现这个函数,因为在通过Runtime获取属性列表时,会获取到一个名字为hash的属性名,这个是系统帮你生成的一个属性
    - (void)setValue:(id)value forUndefinedKey:(NSString *)key {}
    

    Swift方式:

    我们给NSObject写个扩展,让其遵守NSCopying协议,另外自定义的类同样需要实现setValueForUndefinedKey函数

    let m1 = CustomModel()
    m1.name = "Shaw"
    m1.age = 27
            
    let m2 = m1.copy() as! CustomModel
    m2.name = "CTT"
    m2.age = 28
            
    print("\(m1.age!)&\(m2.age!)")
    // 打印结果:27&28
    
    class CustomModel: NSObject {
        public var name: String?
        public var age: Int?
        override func setValue(_ value: Any?, forUndefinedKey key: String) {}
    }
    
    extension NSObject: NSCopying {
        public func copy(with zone: NSZone? = nil) -> Any {
            let copy = self.classForCoder.alloc()
            let mirror = Mirror(reflecting: self)
            for (label, value) in mirror.children {
                guard let label = label else { continue }
                copy.setValue(value, forKey: label)
            }
            return copy
        }
    }
    

    如果父类实现了深拷贝时,子类如何实现深拷贝?如果父类没实现深拷贝,子类如何实现?

    父类实现深拷贝之后,子类只要重写copyWithZone方法,在方法内部调用父类的copyWithZone方法,之后实现自己的属性的处理;父类没有实现深拷贝,子类除了需要对自己的属性进行处理,还要对父类的属性进行处理。

    相关文章

      网友评论

          本文标题:iOS如何实现自定义类的深拷贝?

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