-
Notifications
You must be signed in to change notification settings - Fork 75
Added implementation for NSUbiquitousKeyValueStore #237
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
russhwolf
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the contribution! I've never worked with NSUbiquitousKeyValueStore so I want to make sure everything works as expected before merging this.
The most important item to that end is to make sure this class passes the test suite for Settings implementations, in order to verify that it behaves as expected. This means adding a test class that extends BaseSettingsTest. Because it requires entitlements, this takes a bit of setup. You can use the keychain-tests module as a template.
I have other priorities at the moment so I don't expect to get this merged before the next library release (1.4.0).
...rm-settings/src/appleMain/kotlin/com/russhwolf/settings/NSUbiquitousKeyValueStoreSettings.kt
Outdated
Show resolved
Hide resolved
...rm-settings/src/appleMain/kotlin/com/russhwolf/settings/NSUbiquitousKeyValueStoreSettings.kt
Outdated
Show resolved
Hide resolved
| callback.invoke() | ||
| } | ||
| val observer = NSNotificationCenter.defaultCenter.addObserverForName( | ||
| name = NSUbiquitousKeyValueStoreDidChangeExternallyNotification, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not certain this will work as intended. The documentation for NSUbiquitousKeyValueStoreDidChangeExternallyNotification suggests that notifications are only served from external changes, meaning that if we update a value in-app it won't propagate to listeners. This would break the expectations of ObservableSettings
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are correct here. The notification does not trigger to the app which made the change, which is, as I understand, your intended function.
The notification from the NSUbiquitousKeyValueStore changes is only triggered for apps running on other devices.
However, I could not see any other place or way or API to implement external changes notification for the app, therefore I used this one.
From what I read in the documentation, the NSUbiquitousKeyValueStore does not send notification to the local app at all.
If you have any idea or suggestion on how to implement this in a different way, please let me know. I can rewrite the code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll have to think about this some. I'm not sure whether it makes sense to use ObservableSettings instead of Settings here. Do we eventually see updated values on get calls even without subscribing to external notifications?
| internal expect fun NSUbiquitousKeyValueStore.intForKey(defaultName: String): Int | ||
| internal expect fun NSUbiquitousKeyValueStore.setInt(value: Int, forKey: String) | ||
| internal expect fun NSUbiquitousKeyValueStore.longForKey(defaultName: String): Long | ||
| internal expect fun NSUbiquitousKeyValueStore.setLong(value: Long, forKey: String) | ||
| internal expect fun NSUbiquitousKeyValueStore.setFloat(value: Float, forKey: String) | ||
| internal expect fun NSUbiquitousKeyValueStore.floatForKey(defaultName: String): Float |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's no reason to use expect/actual for these if the implementations are the same for 32-bit and 64-bit systems.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I said, not fully understanding the library implementation I tried to keep it as close to the NSUserDefaults as possible. I can rewrite this part if you want. Please confirm.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, please rewrite it without expect/actual
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
|
|
||
| private fun addListener(key: String, callback: () -> Unit): SettingsListener { | ||
| val block = { _: NSNotification? -> | ||
| callback.invoke() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably should be caching the previous value, similar to other implementations, in order to avoid triggering the listener when nothing has changed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ran several tests and have it working in my app. It looks like the NSUbiquitousKeyValueStore takes care of avoiding notifications if nothing changed. So, it basically handles it itself efficiently. Therefore, from my experience, caching here is not needed for the NSUbiquitousKeyValueStore implementation. However, I can put it back for consistency with other implementations.
Please confirm that this is what you want.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The issue is, if you have two different keys "a" and "b" but you're only observing "a", the notification will trigger for changes to both "a" and "b". The cache ensures that the update callbacks only trigger when the key you're observing changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added cache back and confirmed it works as expected during my tests.
…ings/NSUbiquitousKeyValueStoreSettings.kt Yes, I agree, this makes sense. Co-authored-by: Russell Wolf <russhwolf@users.noreply.github.com>
…ings/NSUbiquitousKeyValueStoreSettings.kt Ok, TBH, when I was working on the code, I did not fully understand the existing implementation and therefore, tried to keep the new class as close to the NSUserDefaults implementation as possible. Co-authored-by: Russell Wolf <russhwolf@users.noreply.github.com>
|
Hopefully with my recent commits all concerns are resolved. |
|
I'd like to get tests running against this as well. I can take a pass at it at some point but probably not soon. |
|
Any ETA on this? Soon to fork and apply @arthef's work. |
|
No ETA, sorry. I don't want to merge this without having tests running against it. Open to contributions there. If you want it sooner you should be able to just copy |
Using
NSUbiquitousKeyValueStoresettings can be automatically shared between devices. The implantation follows convention of other implementations and is mainly based on theNSUserDefaultsSettingscode.Except standard initialization, no other special code is needed. However, to make key-value storage work, the app needs to be correctly configured in Xcode:
In the app project, TARGETS, Signing & Capabilities a new capability needs to be added (
+ Capability):Also, it is highly recommended to add and implement external change listener(s) to make the app aware of the settings change on other device.