如果我们在swift类的Array属性上提供didSet观察者,那么我们将能够观察整个数组中的变化我们如何在数组上进行细粒度观察,我们可以跟踪插入,更新和删除?似乎仅仅使用didSet观察者无济于事。知道如何做到这一点?我遇到了一个link 这似乎解释了我正在寻找的东西,但理解起来有些复杂。任何人都可以提供一个简单的例子来解决这个问题吗? 感谢
答案 0 :(得分:5)
如果要在设置属性之前调查“旧”值(计算差异),则需要使用willSet
,而不是didSet
。在didSet
中计算更改已经太晚了(显然......)
样品:
class AWrap {
var values : [ String ] = [] {
willSet {
print("values: \(values)")
print(" new: \(newValue)")
let old = Set(values)
let new = Set(newValue)
let newElements = new.subtracting(old)
let goneElements = old.subtracting(new)
print(" +: \(newElements)")
print(" -: \(goneElements)")
}
}
}
运行:
let a = AWrap()
a.values.append("2")
a.values.append("3")
a.values.remove(at:0)
给出:
values: []
new: ["2"]
+: ["2"]
-: []
values: ["2"]
new: ["2", "3"]
+: ["3"]
-: []
values: ["2", "3"]
new: ["3"]
+: []
-: ["2"]
答案 1 :(得分:1)
如果您要在多个地方执行此操作,您可以在扩展程序中概括检测,以便更轻松地进行管理:
extension Array where Element:Comparable
{
func changesFrom(old:[Element]) -> [(index:Int, mod:String, old:Element, new:Element, desc:String)]
{
var changes:[(index:Int, mod:String, old:Element, new:Element, desc:String)]
changes = zip(old,self).enumerate()
.filter{ $1.0 != $1.1 }
.map{ ($0, "∆", $1.0, $1.1 , "\($1.0) -> \($1.1)") }
changes += (old.count..<max(old.count,self.count))
.map{ ($0, "+", self[$0], self[$0], "\(self[$0])") }
changes += (self.count..<max(old.count,self.count))
.map{ ($0, "-", old[$0], old[$0], "\(old[$0])" ) }
return changes
}
func printChangesFrom(old:[Element])
{
for changed in changesFrom(old)
{
print( "[\(changed.index)] \(changed.mod) \(changed.desc)" )
}
}
}
class ContainsArray
{
var array = [1,2,3,4]
{
didSet
{
array.printChangesFrom(oldValue)
}
}
}
var CA = ContainsArray()
print("change an element")
CA.array[2] = 7
//[2] ∆ 3 -> 7
print("change multiple elements")
CA.array.sortInPlace(<)
//[2] ∆ 7 -> 4
//[3] ∆ 4 -> 7
print("add elements")
CA.array += [9,12,14]
//[4] + 9
//[5] + 12
//[6] + 14
print("remove Elements")
CA.array.removeLast(3)
//[4] - 9
//[5] - 12
//[6] - 14