我希望能够在Swift中复制自定义类.到现在为止还挺好.在Objective-C中,我只需要实现NSCopying
协议,这意味着实现copyWithZone
.
举个例子,我有一个叫做Value
存储a 的基本类NSDecimalNumber
.
func copyWithZone(zone: NSZone) -> AnyObject! {
return Value(value: value.copy() as NSDecimalNumber)
}
Run Code Online (Sandbox Code Playgroud)
在Objective-C I中,可以轻松地调用copy
复制我的对象.在Swift中,似乎没有办法打电话copy
.copyWithZone
即使不需要区域,我真的需要打电话吗?我需要将哪个区域作为参数传递?
Sul*_*han 30
该copy
方法定义于NSObject
.如果您的自定义类不继承NSObject
,copy
则无法使用.
您可以copy
通过以下方式为任何对象定义:
class MyRootClass {
//create a copy if the object implements NSCopying, crash otherwise
func copy() -> Any {
guard let asCopying = ((self as AnyObject) as? NSCopying) else {
fatalError("This class doesn't implement NSCopying")
}
return asCopying.copy(with: nil)
}
}
class A : MyRootClass {
}
class B : MyRootClass, NSCopying {
func copy(with zone: NSZone? = nil) -> Any {
return B()
}
}
var b = B()
var a = A()
b.copy() //will create a copy
a.copy() //will fail
Run Code Online (Sandbox Code Playgroud)
我想这copy
不是一个纯粹的Swift复制对象的方式.在Swift中,它可能是创建复制构造函数(一种采用相同类型的对象的初始化程序)的更常用方法.
Dan*_*aan 18
您可以编写自己的复制方法
class MyRootClass {
var someVariable:Int
init() {
someVariable = 2
}
init(otherObject:MyRootClass) {
someVariable = otherObject.someVariable
}
func copy() -> MyRootClass {
return MyRootClass(self)
}
}
Run Code Online (Sandbox Code Playgroud)
这样做的好处是当您在项目周围使用子类时,可以调用'copy'命令,它将复制子类.如果您只是初始化一个要复制的新类,您还必须为每个对象重写该类...
var object:Object
....
//This code will only work for specific class
var objectCopy = Object()
//vs
//This code will work regardless of whether you are using subClass or superClass
var objectCopy = object.copy()
Run Code Online (Sandbox Code Playgroud)
Mis*_*ewb 17
好吧,有一个非常简单的解决方案,你不必创建根类.
protocol Copyable {
init(instance: Self)
}
extension Copyable {
func copy() -> Self {
return Self.init(instance: self)
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果要使自定义类能够复制,则必须使其符合Copyable
协议并提供init(instance: Self)
实现.
class A: Copyable {
var field = 0
init() {
}
required init(instance: A) {
self.field = instance.field
}
}
Run Code Online (Sandbox Code Playgroud)
最后,您可以func copy() -> Self
在任何A
类的实例上使用它来创建它的副本.
let a = A()
a.field = 1
let b = a.copy()
Run Code Online (Sandbox Code Playgroud)
就我而言,对象链很大并且嵌套,因此正在寻找更简单的解决方案。
核心概念非常简单...通过新的初始化复制数据,我使用Encode
和Decode
来深度复制整个对象,因为我的对象已经符合Codable
,
class MyCodableObject: Codable, CustomStringConvertible {
var name: String
var description: String { name }
init(name: String) {
self.name = name
}
}
let originalArr = [MyCodableObject(name: "a"),
MyCodableObject(name: "b")]
do {
let data = try JSONEncoder().encode(originalArr)
let copyArr = try JSONDecoder().decode([MyCodableObject].self, from: data)
//modify if required
copyArr.forEach { obj in
obj.name = "\(obj.name) modified"
}
print(originalArr, copyArr) //-> [a, b] [a modified, b modified]
} catch {
fatalError(error.localizedDescription)
}
Run Code Online (Sandbox Code Playgroud)
为了简化未来的情况,我们可以创建一个提供copy
功能的协议。
对于不可编码的对象,您必须实现自己的copy
函数。
对于Codable
对象,我们可以提供默认实现,以便它可以立即使用。就像这样:
protocol Copyable {
func copy() -> Self
}
extension Copyable where Self: Codable {
func copy() -> Self {
do {
let encoded = try JSONEncoder().encode(self)
let decoded = try JSONDecoder().decode(Self.self, from: encoded)
return decoded
} catch {
fatalError(error.localizedDescription)
}
}
}
Run Code Online (Sandbox Code Playgroud)
我们现在可以使Codable
对象符合我们的Copyable
协议并立即开始使用它。
extension MyCodableObject: Copyable {}
Run Code Online (Sandbox Code Playgroud)
例子:
let a = MyCodableObject(name: "A")
let b = a.copy()
b.name = "B"
print(a.name, b.name) //-> "A B"
Run Code Online (Sandbox Code Playgroud)
我们还可以使对象符合Array
并Codable
立即访问Copyable
该函数:copy
extension Array: Copyable where Element: Codable {}
Run Code Online (Sandbox Code Playgroud)
例子:
let originalArr = [MyCodableObject(name: "a"),
MyCodableObject(name: "b")]
let copyArr = originalArr.copy()
copyArr.forEach { (obj) in
obj.name = "\(obj.name) modified"
}
print(originalArr, copyArr) //-> [a, b] [a modified, b modified]
Run Code Online (Sandbox Code Playgroud)
小智 5
IMO,实现这一目标的最简单方法是:
protocol Copyable
{
init(other: Self)
}
extension Copyable
{
func copy() -> Self
{
return Self.init(other: self)
}
}
Run Code Online (Sandbox Code Playgroud)
在结构中实现为:
struct Struct : Copyable
{
var value: String
init(value: String)
{
self.value = value
}
init(other: Struct)
{
value = other.value
}
}
Run Code Online (Sandbox Code Playgroud)
并且,在一个班级中,作为:
class Shape : Copyable
{
var color: NSColor
init(color: NSColor)
{
self.color = color
}
required init(other: Shape)
{
color = other.color
}
}
Run Code Online (Sandbox Code Playgroud)
并且在这样的基类的子类中:
class Circle : Shape
{
var radius: Double = 0.0
init(color: NSColor, radius: Double)
{
super.init(color: color)
self.radius = radius
}
required init(other: Shape)
{
super.init(other: other)
if let other = other as? Circle
{
radius = other.radius
}
}
}
class Square : Shape
{
var side: Double = 0.0
init(color: NSColor, side: Double)
{
super.init(color: color)
self.side = side
}
required init(other: Shape)
{
super.init(other: other)
if let other = other as? Square
{
side = other.side
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果您希望能够复制可复制类型的数组:
extension Array where Element : Copyable
{
func copy() -> Array<Element>
{
return self.map { $0.copy() }
}
}
Run Code Online (Sandbox Code Playgroud)
然后允许您执行简单的代码,例如:
{
let shapes = [Circle(color: .red, radius: 5.0), Square(color: .blue, side: 5.0)]
let copies = shapes.copy()
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38554 次 |
最近记录: |