应用场景:
需要通过复制对象达到创建新对象的目的。
难点:深拷贝和浅拷贝
初始化一个类或者结构体会消耗大量的内存资源和计算资源,然而通过拷贝是可以节省这些资源的。
值类型的拷贝都是深拷贝,不必多言。
那么如何对引用类型实现深拷贝呢?
答案就是NSCopying协议
class ProductA: NSCopying { var name: String var price: Int init(name:String,price:Int) { self.name = name self.price = price } func copy(with zone: NSZone? = nil) -> Any { return ProductA.init(name: self.name, price: self.price) } }
let p = ProductA.init(name: "book", price: 10) let c = p.copy() as! ProductA c.name = "computer" print(c.name,p.name)
在swift4中你可以暂时忽略zone
那么引用类型中包含引用类型的拷贝呢?
copy(with zone: NSZone? = nil)
只是拷贝的对象的引用,而不是对象的本身,也就会浅拷贝:
class ProductA: NSCopying { var name: String var price: Int var place: PlaceOfOrigin init(name:String,price:Int, place:PlaceOfOrigin) { self.name = name self.price = price self.place = place } func copy(with zone: NSZone? = nil) -> Any { return ProductA.init(name: self.name, price: self.price,place:self.place) } } class PlaceOfOrigin{ var country: String var city: String init(country:String, city:String) { self.country = country self.city = city } }
let p = ProductA.init(name: "book", price: 10, place: PlaceOfOrigin.init(country: "American", city: "NewYork")) let c = p.copy() as! ProductA c.name = "computer" c.place.city = "BeiJing" print(c.name,c.place.city,p.name,p.place.city)
//log::: computer BeiJing book BeiJing
那么如何更改呢?
class ProductA: NSCopying { var name: String var price: Int var place: PlaceOfOrigin init(name:String,price:Int, place:PlaceOfOrigin) { self.name = name self.price = price self.place = place } func copy(with zone: NSZone? = nil) -> Any { return ProductA.init(name: self.name, price: self.price,place:self.place.copy() as! PlaceOfOrigin) } } class PlaceOfOrigin:NSCopying{ var country: String var city: String init(country:String, city:String) { self.country = country self.city = city } func copy(with zone: NSZone? = nil) -> Any { return PlaceOfOrigin.init(country: self.country, city: self.city) } }
///log:::: computer BeiJing book NewYork
下面,我们来看数组复制
var productAs = [ProductA.init(name: "computer", price: 10000, place: PlaceOfOrigin.init(country: "China", city: "BeiJing"))]
func testArray(){ let otherProducts = self.productAs otherProducts[0].name = "hh" print(productAs[0].name,otherProducts[0].name) }
///log: hh hh
ok 我们看到是浅拷贝,那么如何进行深拷贝呢?
let otherProducts = productAs.map { (p) -> ProductA in return p.copy() as! ProductA } otherProducts[0].name = "hh" print(otherProducts[0].name) print(productAs[0].name)
//log : hh computer
使用原型模式,有几个陷阱
1.深复制与潜复制
2.记住可以以克隆的副本,作为下一次的原型