应用场景:
需要通过复制对象达到创建新对象的目的。
难点:深拷贝和浅拷贝
初始化一个类或者结构体会消耗大量的内存资源和计算资源,然而通过拷贝是可以节省这些资源的。
值类型的拷贝都是深拷贝,不必多言。
那么如何对引用类型实现深拷贝呢?
答案就是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.记住可以以克隆的副本,作为下一次的原型