Swift design mode: Prototype and swift design mode prototype
Application scenarios:
You need to copy the object to create a new object.
Difficulties: Deep copy and light copy
Initializing a class or structure consumes a lot of memory resources and computing resources. However, copying can save these resources.
Copy of the value type is a deep copy.
So how to implement deep copy for the reference type?
The answer is the NSCopying protocol.
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)
In swift4, You can temporarily ignore the zone
What if the reference type contains a copy of the reference type?
copy(with zone: NSZone? = nil)
It is just a reference to the Copied object, rather than the object itself. It will also be a small copy:
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
So how can we change it?
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
Next, let's look at array replication.
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
OK. We can see that it is a small copy. How can we perform a deep copy?
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
There are several traps in the prototype mode.
1. Deep replication and latent Replication
2. Remember to use the cloned copy as the next prototype.