Sharing Userdefaults Between Extensions

Sharing UserDefaults between extensions

You cannot use UserDefaults.standard to share data between a host app and its app extension. You instead have to create a shared container with UserDefaults(suiteName:) to share data.

Even though an app extension bundle is nested within its containing
app’s bundle, the running app extension and containing app have no
direct access to each other’s containers.

To enable data sharing, use Xcode or the Developer portal to enable
app groups for the containing app and its contained app extensions.
Next, register the app group in the portal and specify the app group
to use in the containing app.

After you enable app groups, an app extension and its containing app
can both use the NSUserDefaults API to share access to user
preferences. To enable this sharing, use the initWithSuiteName: method
to instantiate a new NSUserDefaults object, passing in the identifier
of the shared group.

For more, refer to: https://developer.apple.com/library/content/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW1

How to use App Groups: https://github.com/pgpt10/Today-Widget

Standard or SuiteName?

Use standard one for data that is only for Host App. Use suiteName for data that you want to share between Extension and Host App. Just don't persist the same data in both of them. Avoid data redundancy. Use both of them according to the context.

Shared UserDefaults between app and extension not working correctly

I would recommend to dig down step by step here.

First, make sure that both the main app and the widget extension have app group capability enabled and use the same and activated (the checkmark must be set) app group name:

Main App:
Main App

Today Widget Extension:

Today Widget Extension

Then make a simple test with direct set/get access. In your main app's AppDelegate.didFinishLaunchingWithOptions method (change the app group name and the keys to your needs):

if let userDefaults = UserDefaults(suiteName: "group.de.zisoft.GPS-Track") {
userDefaults.set("test 1" as AnyObject, forKey: "key1")
userDefaults.set("test 2" as AnyObject, forKey: "key2")
userDefaults.synchronize()
}

In your Today Widget Extension's ViewController:

if let userDefaults = UserDefaults(suiteName: "group.de.zisoft.GPS-Track") {
let value1 = userDefaults.string(forKey: "key1")
let value2 = userDefaults.string(forKey: "key2")
...
}

If this works, the problem must be related in your Preferences singleton.

Share Data between Project and Share Extension

Your helper function getDataSourceArray() tries to access UserDefaults.standard which is not shared between your host app and the extension app. You need to use the shared container.

  • UserDefaults.standard -> not shared between host and extension
  • UserDefaults(suiteName:) -> shared between host and extension

Try to change your function to this:

func getDataSourceArray() - > [Wishlist] ? {
if let data = UserDefaults(suiteName: UserDefaults.Keys.groupKey).value(forKey: Keys.dataSourceKey) as ? Data {
if let dataSourceArray =
try ? PropertyListDecoder().decode(Array < Wishlist > .self, from: data) as[Wishlist] {
return dataSourceArray
}
}
return nil
}

Why doesn't NSUserDefaults work between my app & share extension?

Not sure if defaults.addSuite(named: ...) does the same as UserDefaults(suiteName: ...). In my app I use appGroups this way and it works as expected:

// write
if let userDefaults = UserDefaults(suiteName: appGroupName) {
userDefaults.set("---" as AnyObject, forKey: "distance")
userDefaults.set("---" as AnyObject, forKey: "altitude")
...
userDefaults.synchronize()
}

// read
if let userDefaults = UserDefaults(suiteName: appGroupName) {
self.distanceLabel.text = userDefaults.string(forKey: "distance")
self.altitudeLabel.text = userDefaults.string(forKey: "altitude")
}


Related Topics



Leave a reply



Submit