Do something when dictionary values change
Asked Answered
B

2

7

I'm looking for a way to run some code whenever the values of a dictionary changes. I'm still quite new to Swift, but this is what I have so far:

var objects: NSMutableDictionary {
    didChange(changeKind: keyValue, valuesAtIndexes: indexes, forKey: something){

    }
}

This however gives me a compiling error (Use of unresolved identifier something), and whatever I do, I can't seem to make it work. Any ideas?

Beshrew answered 23/12, 2014 at 21:55 Comment(0)
S
8

What you're looking for is the didSet property observer. Usage is as follows:

var objects: NSMutableDictionary? {
    didSet {
        // stuff
    }
}

Note that willSet is another option if you want to be notified just before the property changes instead of just after. In the case of willSet, you're given a newValue variable representing the incoming value of the property and in the case of didSet, an oldValue property representing the outgoing value.

As @Paulw11 brought up below, this will not notify you when the contents of the dictionary change. Only when the variable is reassigned. If you want to be notified whenever the values inside the dictionary are updated, (AFAIK) you have to use an equivalent Swift Dictionary.

var swiftObjects: [NSObject: AnyObject]? {
    didSet {
        println(oldValue)
    }
}
Supplemental answered 23/12, 2014 at 22:30 Comment(8)
Will this notify you when the dictionary itself mutates (which is what I think the OP is after) or only when the value of the property changes (ie a new dictionary is assigned)Tugboat
@Tugboat Come to think of it, no it won't. Updating.Supplemental
Oh, in your second example, are you making your own dictionary, you're not using NSDictionary?Beshrew
@Beshrew correct. The second uses a Swift dictionary rather than the NSMutableDictionary class from Foundation.Supplemental
How to detect what key has changed?Snowcap
I solved it by storing all values in a Set, observing the Set (Arrays and Sets support collection-KVC) and updating the Dictionary accordingly when the Set is changed.Snowcap
From testing just now while working on my own issue, it seems that didSet is actually being called every time that my dictionary is changing. Only ever set the dictionary on initialization and then update that single instance. I'm getting didSet called many many times. Not sure if this has changed in newer version of swift as this question is pretty oldErida
@Erida are you using an NSDictionary or a swift dictionary?Cleanly
C
2

How did you explain this:

class My {
    var dict = [String: String]() {
        didSet {
            print(oldValue)
        }
    }
}

let my = My()
my.dict["asd"] = "asd"
my.dict["bfg"] = "bfg"
my.dict = [String: String]()

Output:

[:]
["asd": "asd"]
["bfg": "bfg", "asd": "asd"]

So didSet called every time new value added.

Cytogenetics answered 24/2, 2022 at 7:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.