4

Hopefully a simple question, but I'm wondering how I would access UserDefaults data saved in my UIKit app from a SwiftUI Widget? I need to display some of this data in a widget.

Thanks!

Noah Evans
  • 309
  • 3
  • 12
  • You need to create an app group – Andrew Sep 26 '20 at 15:11
  • Yes, I’ve got an app group, but it’s the part of actually accessing the data that’s an issue for me. I don’t think it’s as simple as defining UserDefaults.standard as in my actual app. Thanks though. – Noah Evans Sep 26 '20 at 16:18
  • See [Share data between main App and Widget in SwiftUI for iOS 14](https://stackoverflow.com/questions/63922032/share-data-between-main-app-and-widget-in-swiftui-for-ios-14) or [Sharing Data with AppGroup](https://stackoverflow.com/questions/63995776/sharing-data-with-appgroup) – pawello2222 Sep 28 '20 at 16:39

1 Answers1

8

You need to use UserDefaults(suiteName:) instead of UserDefaults.standard along with an AppGroup. UserDefaults.standard is only accessible in the app that it is in, it is not available to any of the extensions or other apps that you may make. This is why you have to use an AppGroup.

Once you have created your AppGroup (you can do this in the Signing and Capabilities section) you should have a suiteName for it, something like:

group.com.my.app.identifier

Then in your UIKit part of your app you can set the values in the AppGroup's UserDefaults in the following way:

if let userDefaults = UserDefaults(suiteName: "group.com.my.app.identifier") {
    userDefaults.setValue("value to save", forKey: "Key")
}

And reading them back you can use:

if let userDefaults = UserDefaults(suiteName: "group.com.my.app.identifier") {
    let value = userDefaults.string(forKey: "Key")
}

As the Widget will be written in SwiftUI you can use the property wrapper @AppStorage to access the values:

@AppStorage("Key", store: UserDefaults(suiteName: "group.com.my.app.identifier"))
var value: String = ""

If you have already stored the values that you wish to use in UserDefaults.standard you will need to copy them across to the UserDefaults(suitName:).

Andrew
  • 26,706
  • 9
  • 85
  • 101
  • Thank you so much! Again, probably quite simple, but I wanted to be sure it's right, how would I transfer values from `UserDefaults.standard` to the suite? :) – Noah Evans Sep 26 '20 at 20:38
  • 1
    There is no straightforward way to do it. The easiest solution is to just save all the values that you need to be shared exclusively in the suite. If you have the values in standard then you will have to copy them across (probably at app launch). The only way I know to copy is to read from standard and save in the suite. You should also make sure that any defaults that you need in multiple places are updated to use the suite so you don’t have to perform the copy operation again. – Andrew Sep 27 '20 at 07:22
  • 3
    Bear in mind that the `@AppStorage` wrapper will not update the view. The value will be read once but never updated as views in Widgets are *static* and refreshed by Provider only. – pawello2222 Sep 28 '20 at 16:46