首页 文章

swift中对象数组的深层复制

提问于
浏览
5

我有这个名为Meal的课程

class Meal {
    var name : String = ""
    var cnt : Int = 0
    var price : String = ""
    var img : String = ""
    var id : String = ""

    init(name:String , cnt : Int, price : String, img : String, id : String) {
        self.name = name
        self.cnt = cnt
        self.price = price
        self.img = img
        self.id = id
    }
}

我有一系列的餐:

var ordered = [Meal]()

我想复制该数组,然后对其中一个中的Meal实例进行一些更改而不更改第二个中的Meal实例,我将如何制作它的深层副本?

这个搜索结果对我没有帮助How do I make a exact duplicate copy of an array?

4 回答

  • 12

    由于 ordered 是一个快速数组,声明

    var orderedCopy = ordered
    

    将有效地制作原始数组的副本 .

    但是,由于膳食是 class ,新数组将包含对原始膳食中提到的相同膳食的引用 .

    如果你想要复制膳食内容,那么在一个阵列中改变一顿饭不会改变另一个阵列中的一顿饭,那么你必须将膳食定义为 struct ,而不是作为一个类:

    struct Meal { 
      ...
    

    来自Apple book

    使用struct创建结构 . 结构支持许多与类相同的行为,包括方法和初始化器 . 结构和类之间最重要的区别之一是结构在代码中传递时总是被复制,但类是通过引用传递的 .

  • 8

    要改进@Kametrixom,请检查以下内容:对于普通对象,可以实现的是实现支持复制的协议,并使对象类实现此协议,如下所示:

    protocol Copying {
        init(original: Self)
    }
    
    extension Copying {
        func copy() -> Self {
            return Self.init(original: self)
        }
    }
    

    然后是用于克隆的Array扩展:

    extension Array where Element: Copying {
        func clone() -> Array {
            var copiedArray = Array<Element>()
            for element in self {
                copiedArray.append(element.copy())
            }
            return copiedArray
        }
    }
    

    这就是它,查看代码和示例检查这个gist

  • 9

    正如@MarioZannone所提到的,你要么必须使它成为一个结构,因为结构会自动复制,或者你可能不需要结构并需要一个类 . 为此,您必须定义如何复制您的类 . 有一个 NSCopying 协议在ObjC世界中统一了这个,但这使得你的Swift代码"unpure"必须从 NSObject 继承 . 但我建议你定义自己的复制协议,如下所示:

    protocol Copying {
        init(original: Self)
    }
    
    extension Copying {
        func copy() -> Self {
            return Self.init(original: self)
        }
    }
    

    您可以这样实现:

    class Test : Copying {
        var x : Int
    
        init() {
            x = 0
        }
    
        // required initializer for the Copying protocol
        required init(original: Test) {
            x = original.x
        }
    }
    

    在初始化程序中,您必须将所有状态从传递的 original Test 复制到 self . 既然你正确地实现了协议,你可以这样做:

    let original = Test()
    let stillOriginal = original
    let copyOriginal = original.copy()
    
    original.x = 10
    
    original.x         // 10
    stillOriginal.x    // 10
    copyOriginal.x     // 0
    

    这与没有ObjC的 NSCopying 基本相同

    编辑:可悲的是,这个非常漂亮的协议工作非常糟糕的子类化...

  • 0

    一种简单快捷的方法是将原始数组映射到新副本:

    let copyOfPersons: [Person] = allPersons.map({(originalPerson) -> Person in
            let newPerson = Person(name: originalPerson.name, age: originalPerson.age)
            return newPerson
        })
    

    新人将有不同的指针,但值相同 .

相关问题