Ollie
Ollie

Reputation: 1946

Observe values added to Set - Swift

Is it possible to observe values being added to a Set data-structure?

What i'm trying to achieve:

var storedStrings = Set<String>() {
    didSet (value) {
        // where value is a string that has been added to the Set
    }
}

Example:
storedStrings.insert("hello")
didSet called, as a new value has been added.

storedString.insert("world")
didSet called again.

storedString.insert("hello")
didSet not called, as the set already contains the string "hello"

Upvotes: 3

Views: 796

Answers (3)

dfrib
dfrib

Reputation: 73196

You could implement your own inserter for your set, which could emulate the use of a property observer, making use of the fact that the insert method of Set returns a tuple whose first member is false in case the element to be inserted is already present.

func insert(Element)

Inserts the given element in the set if it is not already present.

From the language reference.

E.g.:

struct Foo {
    private var storedStrings = Set<String>()

    mutating func insertNewStoredString(_ newString: String) {
        if storedStrings.insert(newString).0 {
            print("Inserted '\(newString)' into storedStrings")
        }
    }
}

var foo = Foo()
foo.insertNewStoredString("hello") // Inserted 'hello' into storedStrings
foo.insertNewStoredString("hello") 
foo.insertNewStoredString("world") // Inserted 'world' into storedStrings

Upvotes: 0

Ollie
Ollie

Reputation: 1946

The insert function returns a tuple with the definition: (inserted: Bool, memberAfterInsert: Element).

Therefore the check for a new unique element can be made on insertion instead of using didSet.

var storedStrings = Set<String>()

var insertionResult = storedStrings.insert("Hello")
if insertionResult.inserted {
    print("Value inserted") // this is called
}

insertionResult = storedStrings.insert("Hello")
if insertionResult.inserted {
    print("Value inserted") // this isn't called
}

Upvotes: 4

0x416e746f6e
0x416e746f6e

Reputation: 10136

This can be a bit expensive, but you still can do something like:

var storedStrings = Set<String>() {
    didSet {
        if storedStrings != oldValue {
            print("storedStrings has changed")
            let added = storedStrings.subtracting(oldValue)
            print("added values: \(added)")
            let removed = oldValue.subtracting(storedStrings)
            print("removed values: \(removed)")
        }
    }
}

Upvotes: 5

Related Questions