[swift-users] How do you call willChangeValue(for:, withSetMutation:, using:) ?

Marco Masser lists at duckcode.com
Mon Nov 27 10:15:13 CST 2017

I’m trying to call this method to implement KVO in Swift:

func willChangeValue<Value>(for keyPath: KeyPath<Self, Value>, withSetMutation mutation: NSKeyValueSetMutationKind, using set: Set<Value>) -> Void

That method is defined in the standard library here:
https://github.com/apple/swift/blob/a550042391dcdc0a766a7d67f42d06fc0e92e90c/stdlib/public/SDK/Foundation/NSObject.swift#L210 <https://github.com/apple/swift/blob/a550042391dcdc0a766a7d67f42d06fc0e92e90c/stdlib/public/SDK/Foundation/NSObject.swift#L210>

This is my code:

class Person: NSObject {

    @objc dynamic var nicknames: Set<String> = []

    func addNickname(_ nickname: String) {
        var keyPath: KeyPath<Person, String> = ... // ???
        willChangeValue(for: keyPath, withSetMutation: .union, using: [nickname])
        didChangeValue(for: keyPath, withSetMutation: .union, using: [nickname])


The explicit type for that keyPath constant in the addNickname() method is exactly what the declaration of willChangeValue(for:, withSetMutation:, using:) wants and the compiler is happy with the way I wrote it here. It’s obvious that the KeyPath’s first generic type argument is the Person class itself and the second generic type argument is the type of whatever is inside the set. But I can’t find a way to actually write a keyPath that references a collection’s Element type.

Writing the property name itself yields a keyPath to the type of the property, which is Set<String>, obviously:

keyPath = \Person.nicknames // ReferenceWritableKeyPath<Person, Set<String>>

I got creative and tried things like the following, but that only results in compiler errors telling me it’s ambiguous without more context or that a KeyPath must begin with a type:

keyPath = \Person.nicknames.Self.Element

What do I have to write to actually get String instead of Set<String> there?

Ideally that would also work with an NSMutableSet, not just Set<String> because that’s what I actually need.

Thanks in advance,

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20171127/a90f91fb/attachment.html>

More information about the swift-users mailing list