If we provide a didSet observer on an Array property in swift class then we will be able to observe changes in the array as a whole How we can do a fine grained observation on array where we be able to track insertions , updations and deletions ? It seems merely using didSet observer alone will not help. Any idea how it can be done ? I came across a link that seems to explain the thing that I am looking for but it is somewhat complex to understand. Can anybody provide a simple example to solve this problem ? Thanks
If you want to investigate the 'old' value before the property is set (to calculate a diff), you need to use willSet
, not didSet
. In didSet
it is too late to calculate changes (obviously ...)
Sample:
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)")
}
}
}
Running that:
let a = AWrap()
a.values.append("2")
a.values.append("3")
a.values.remove(at:0)
Gives:
values: []
new: ["2"]
+: ["2"]
-: []
values: ["2"]
new: ["2", "3"]
+: ["3"]
-: []
values: ["2", "3"]
new: ["3"]
+: []
-: ["2"]
You can generalize the detection in an extension to make it easier to manage if you're going to do this in several places:
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With