iOS 实现自定义对象深拷贝(OC/Swift)
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