iOS如何實現(xiàn)自定義類的深拷貝?

遵守NSCopying協(xié)議,實現(xiàn)copyWithZone方法,在方法中新創(chuàng)建一個對象,然后對于OC和Swift來說有些區(qū)別,OC利用runtime來獲取原對象的屬性列表,然后通過KVC的方式給新對象進行賦值,注意需要實現(xiàn)setValueForUndefinedKey函數(shù);而Swift可以通過Mirror反射,來動態(tài)獲取原對象屬性,然后再進行賦值操作。

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;
}
// 注意此處需要實現(xiàn)這個函數(shù),因為在通過Runtime獲取屬性列表時,會獲取到一個名字為hash的屬性名,這個是系統(tǒng)幫你生成的一個屬性
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {}

Swift方式:

我們給NSObject寫個擴展,讓其遵守NSCopying協(xié)議,另外自定義的類同樣需要實現(xiàn)setValueForUndefinedKey函數(shù)

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
    }
}

如果父類實現(xiàn)了深拷貝時,子類如何實現(xiàn)深拷貝?如果父類沒實現(xiàn)深拷貝,子類如何實現(xiàn)?

父類實現(xiàn)深拷貝之后,子類只要重寫copyWithZone方法,在方法內部調用父類的copyWithZone方法,之后實現(xiàn)自己的屬性的處理;父類沒有實現(xiàn)深拷貝,子類除了需要對自己的屬性進行處理,還要對父類的屬性進行處理。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容