sindresorhus / Defaults

💾 Swifty and modern UserDefaults

Home Page:https://swiftpackageindex.com/sindresorhus/Defaults/documentation/defaults

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Handle key with a dot

kmalyshev opened this issue · comments

Hello,
I am not sure if it's a bug or I am doing something wrong. I have a setting window that users can change settings in. It uses property wrapper '@default(.key)' for textfields.

However in other piece of code (ViewModel) I am subscribed to changes

            Defaults.observe(
                keys: .key1, .key2,
                options: [] // Initial value is not needed.
            ) { [weak self] in
                guard let self = self else { return }
                self.updateValues(array: &self.items)
            }
            .tieToLifetime(of: self)

It never gets called even though values are properly saved. I have to manually call update viewModel method after each change. Is it a bug or I'm using the API in a wrong way?

I'm using @Default without problems in multiple apps.

Are you using @Default in a SwiftUI view or a view model? Because it cannot be used in a view model.

I cannot really help much without more info and code.

I use @default in SwiftUI view.

@Default(.isOn) var isOn

and then i have a toggle
Toggle("Pro mode", isOn: $isOn)

switching it back and forth doesn't trigger the observation closure.

I also tried observing using publisher and '.sink'. Closure after '.sink' never gets triggered.
Defaults.publisher(keys: .isOn)
This observation code is in AppDelegate.

If this information is not enough and it doesn't seem that I'm doing something completely wrong - i can make a tiny project showing what's not working.

I'm using both Defaults.observe and Defaults.publisher in my apps without any problems. It would be helpful if you could provide something I could run so I can debug the issue.

I also tried observing using publisher and '.sink'. Closure after '.sink' never gets triggered.

Maybe try Defaults.publisher(.isOn)? (No keys parameter) Just to rule out that method being the problem.

Found the problem.

static let proMode = Key<Bool>("name", default: false)
works well

static let proMode = Key<Bool>("some.name", default: false)
doesn't work. If there is a period in the name - observation doesn't happen.

https://github.com/kmalyshev/DefaultsLibTest/

if you remove "." from the name in this file the UI starts working again.
https://github.com/kmalyshev/DefaultsLibTest/blob/main/DefaultsTest/DefaultsSettings.swift

That is super weird. I cannot imagine what would cause this to fail.


// @hank121314 In case you have any ideas.

I went to docs of KVO, this is not an issue with your code, it's their design which i didn't know about. Dot notation is used to observe subproperties.

object?.addObserver(self, forKeyPath: key, options: options.toNSKeyValueObservingOptions, context: nil)
https://stackoverflow.com/a/14172860/605013

I'll close the bug. Sorry for the time spent on that.

This is a bug in Defaults. We should correctly escape any dot in the observation code path.

commented

This is a bug in Defaults. We should correctly escape any dot in the observation code path.

Thanks for mentioning this issue! FWIW, it'll be great if this bug can be fixed in the future releases. 🥰

Seems like there is no way to escape special characters for an Objective-C key path, so there is really no way to fix this.