如果我们在swift类中的Array属性上提供一个didSet观察器,那么我们将能够观察到整个数组的变化。我们如何对数组进行细粒度观察,从而跟踪插入、更新和删除?仅仅使用didSet观察者似乎无济于事。知道怎么做吗?我偶然发现了一个链接这似乎解释了我想要的东西,但理解起来有些复杂。有人能提供一个简单的例子来解决这个问题吗?感谢
如果要在设置属性之前调查"旧"值(以计算差异),则需要使用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"]
如果要在以下几个地方进行检测,您可以在扩展中推广检测,使其更易于管理:
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