普通视图

发现新文章,点击刷新页面。
昨天 — 2025年5月20日首页

iOS 实现自定义对象深拷贝(OC/Swift)

作者 章鱼paul帝
2025年5月20日 11:26

iOS 实现自定义对象深拷贝(OC/Swift)

在 OC 中,对象的赋值操作是浅拷贝(指针复制),创建一个指针,旧对象引用对象计数加 1。在 Swift 中,类是引用类型,引用类型在赋值和传参时都是操作的引用,这些引用指向同一个对象。如下,对 classA 的修改也会影响到 classB:


classTestClass{        

  var str = "my class"

}

let classA =TestClass()

let classB =classA

classA.str="your class"

print(classB.str)    //your class

接下来介绍下如何分别在 OC 和 Swift 中实现自定义对象深拷贝

OC 方式:

遵守 NSCopying 协议,实现 copyWithZone 方法,通过 Runtime 实现自定义类的深拷贝,核心思路是 动态遍历类的所有属性并递归复制其值


@interface TestObject : NSObject<NSCopying>

@property (nonatomic, strong) NSString *name;

@property (nonatomic, assign) int age;

@end

  


@implementation TestObject

- (id)copyWithZone:(NSZone *)zone {

    TestObject *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;

}

@end

  


//调用  

TestObject *testObject = [[TestObject alloc] init];

testObject.name = @"test";

testObject.age = 10;

  


TestObject *copyObject = [testObject copy];

NSLog(@"copyObject:%@ %ld", copyObject.name,copyObject.age);// 打印结果:test&10

Swift 方式:

1. 遵循 NSCopying 协议(适用于继承自 NSObject 的类)

在下述示例中,Person 类和其属性 Address 类都遵循了 NSCopying 协议,并在 copy(with:) 方法中   实现了各自的深拷贝逻辑。


class Address: NSObject, NSCopying {

    var city: String

  


    init(city: String) {

        self.city = city

    }

  


    func copy(with zone: NSZone? = nil) -> Any {

        return Address(city: self.city)

    }

}

  


class Person: NSObject, NSCopying {

    var name: String

    var address: Address

  


    init(name: String, address: Address) {

        self.name = name

        self.address = address

    }

  


    func copy(with zone: NSZone? = nil) -> Any {

        let addressCopy = self.address.copy() as! Address

        return Person(name: self.name, address: addressCopy)

    }

}

2. 使用 Codable 协议进行序列化与反序列化(适用于纯 Swift 类)

如果你的类不继承自 NSObject,可以通过让类遵循 Codable 协议,利用 JSON 编码与解码来实现深拷贝。


extension Encodable where Self: Decodable {

    func deepCopy() -> Self? {

        do {

            let data = try JSONEncoder().encode(self)

            return try JSONDecoder().decode(Self.self, from: data)

        } catch {

            print("深拷贝失败: \(error)")

            return nil

        }

    }

}


// 要求类实现Codable协议

class Person: Codable {

    var name: String

    var friends: [Person]

    

    init(name: String, friends: [Person]) {

        self.name = name

        self.friends = friends

    }

}

//调用

let alice = Person(name: "Alice", friends: [])

let bob = Person(name: "Bob", friends: [alice])


if let bobCopy = bob.deepCopy() {

    print(bobCopy.name,bobCopy.friends) // "Bob [Person]"

}

3. 自定义 Copyable 协议(适用于纯 Swift 类)


protocol Copyable {

    func copy()-> Self

}


class MyClass:Copyable{

    var des = " "

    func copy() -> Self{


    let obj = self.dynamicType.init(self.des)

        return obj

    }

    required init(_ des:String){

        self.des = des

    }

}


let myClass = MyClass("my class")

let yourClass = myClass.copy()

yourClass.des = "your class"

print(yourClass.des)//your class

print(myClass.des)// my class

  


class Son:MyClass{

}

let sonA = Son("sonA")

let sonB = sonA.copy()

sonB.des = "sonB"

print(sonA.des)//sonA

print(sonB.des)//sonB

❌
❌