App group shared user defaults

In iOS 16 beta 3, my iOS app sets some strings in the shared user defaults of the app group. The iOS widget extension reads the strings from the shared user defaults correctly, but the watchOS app and watchOS widget extension could not read them (get nil). Integers stored in the shared user defaults can be read everywhere. All targets are in the same app group. Does anyone have similar problems?

Answered by DTS Engineer in 722189022

It's new code.

On modern systems your watchOS code runs on the watch, meaning that you can’t share state between it and the containing iPhone app using user defaults [1]. If you want to share state like this, do that as you would in any other device-to-device situation, for example:

  • iCloud key-value store (NSUbiquitousKeyValueStore)

  • Watch Connectivity

  • CloudKit

  • Third-party cloud platforms

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Way back in the day part of your watchOS app, the WatchKit app extension, did run the iPhone, but that hasn’t been the case for years.

Is this new in iOS 16.0b3? If so, what previous release did this work on?

Or is this new code and you just happen to have first tested it on iOS 16.0b3?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

It's new code. After sharing data with statements like following:

@AppStorage("variable", store: UserDefaults(suiteName: "group.com.company.App")) var variable

I don't seem to get any data shared from iOS app to watch app. Xcode 14 beta 3 gives warning:

[User Defaults] Couldn't read values in CFPrefsPlistSource<0x14698af0> (Domain: group.com.company.App, User: kCFPreferencesAnyUser, ByHost: Yes, Container: (null), Contents Need Refresh: Yes): Using kCFPreferencesAnyUser with a container is only allowed for System Containers, detaching from cfprefsd

Accepted Answer

It's new code.

On modern systems your watchOS code runs on the watch, meaning that you can’t share state between it and the containing iPhone app using user defaults [1]. If you want to share state like this, do that as you would in any other device-to-device situation, for example:

  • iCloud key-value store (NSUbiquitousKeyValueStore)

  • Watch Connectivity

  • CloudKit

  • Third-party cloud platforms

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

[1] Way back in the day part of your watchOS app, the WatchKit app extension, did run the iPhone, but that hasn’t been the case for years.

So... this modern system distributes the watchOS with the iOS but they can't belong to the same app 'group' for sharing 'state' or whatever data bits you had been able to share back in the day. While apps distributed separately can share data if they belong to the app 'group' ? Am I getting that right?

Am I getting that right?

I don’t think so.

This isn’t about how the apps are distributed, it’s about how they are run. Way back in the day, watchOS apps weren’t actually run on the watch. Rather, they were run on the paired iPhone and their UI actions were bridged over to the watch. Kind like screen sharing for the world’s tinies screen (-: In that case the watchOS app (well, app extension) and its container iOS app were always running on the same device (the paired iPhone) and they could share state using the file system.

Modern versions of watchOS run the watchOS app on the watch itself, which means that share state using the file system is no longer feasible because the watchOS app is talking to the watch file system and the iOS app is talking to the iPhone file system. So, to share state you have to use some sort of distributed state mechanism, like the ones I mentioned above.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

What about if I want to share a preference between a Watch App WidgetKit Extension (for Watch Face complications) and a Watch app? I don't see how any of the suggested methods would apply to a WidgetKit extension.... This has worked for me previously when sharing between iPhone App and iPhone Widget Extension.

I’m hardly an expert on WidgetKit but I presume that both the watchOS app and the watchOS WidgetKit appex run on the watch itself, and thus could share state using an app group.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

App group shared user defaults
 
 
Q