swift-composable-architecture
swift-composable-architecture copied to clipboard
`@Shared` with `appStorage` doesn't update in extensions
Description
Recently, we were attempting to use @Shared(.appStorage(key))
with several TCA reducer properties in a widget extension, having already used it successfully in the parent app. We updated dependencies.defaultAppStorage
to our own UserDefaults with the correct suite in both the main app and extension, and while this allowed the correct value to be read into each property in the widget initially, the extension never receives updates when the main app writes to the defaults.
While tracing down this issue, we found that it was due to the implementation of AppStorageKey
: it's using UserDefaults.didChangeNotification
to observe changes and update the value, but this notification is documented to not work across processes. Therefore, the values in the extension never update as expected.
The documentation points to KVO as the solution for observing changes even across processes, but it has the very annoying issue that keys with periods won't work due to key paths using periods differently. I tried a solution of this nature and failed on the included test with a key containing periods. So I'm not sure what the correct answer is here, but I think it is somewhat expected that @Shared(.appStorage(key))
properties in an extension with a shared app group would update so I'm filing this issue.
Checklist
- [X] I have determined whether this bug is also reproducible in a vanilla SwiftUI project.
- [X] If possible, I've reproduced the issue using the
main
branch of this package. - [X] This issue hasn't been addressed in an existing GitHub issue or discussion.
Expected behavior
@Shared(.appStorage(key))
properties on TCA reducers used in extensions stay in sync with the main app values when defaultAppStorage
uses UserDefaults(withSuite:)
Actual behavior
@Shared(.appStorage(key))
properties on TCA reducers used in extensions are correct initially, and then are out of sync with the main app values when defaultAppStorage
uses UserDefaults(withSuite:)
Reproducing project
No response
The Composable Architecture version information
main
Destination operating system
iOS 18
Xcode version information
Xcode 16
Swift Compiler version information
swift-driver version: 1.115 Apple Swift version 6.0 (swiftlang-6.0.0.9.10 clang-1600.0.26.2)