Data sharing between WidgetWatchExtension and watchOS/iOS app

When I try to access the data in my IntentTimelineProvider in the recommendations function using App Groups, it is always empty "no data".

func recommendations() -> [IntentRecommendation<IndicatorIntent>] {
        if let sharedUD = UserDefaults(suiteName: "group.measurements") {
            let jm = JanitzaMeasurementValue(identifier: "1", display: "2")
            let intent = IndicatorIntent()
            intent.indicatorWidgetData = jm
            let desc = sharedUD.string(forKey: "string") ?? "no data"
            return [IntentRecommendation(intent: intent, description: desc)]
        }
        
        return []
    }

Although I write this in both the watchOS and iOS app using App Groups.

if let sharedUD = UserDefaults(suiteName: "group.measurements") {
     sharedUD.set("test", forKey: "string")
}

What is the right way to dynamically implement the widgets for Complications in watchOS? Like for example in Shortcuts App.

**Thanks for support **

I have a new insight. If I start the widget extension for watch in Xcode manually and debug it, it works. After that it doesn't work anymore, no matter if I restart apple watch or do something else, as if the recommendations function is no longer called.

The best way to share across iOS / WatchOS would be using NSUbiquitousKeyValueStore to share and sync small, not often changing data with the cloud. App Groups won't work across targets like Watch and iOS because they are different platforms with different App Group file locations. Yes, App Groups can share data but think of them as an on-device thing with available across processes that can access the same App Group location (apps associated with your team ID).

Rico


WWDR | DTS | Software Engineer

To test the proposal, I have created a small sample project.

I use this code in the iOS/watchOS app.

import SwiftUI
import Foundation

struct ContentView: View {
    @State var text: String = ""
    
    init() {
        let store = NSUbiquitousKeyValueStore.default
        store.synchronize()
        if let savedText = getDataFromiCloud(key: "text") {
            _text = .init(initialValue: savedText)
        }
    }
    
    var body: some View {
        VStack {
            TextField("Input", text: $text)
                .padding()
            Button("Submit") {
                saveDataToiCloud(key: "text", value: text)
                print("saved!")
            }
            
        }
        .padding()
    }
    
    func saveDataToiCloud(key: String, value: String) {
        let store = NSUbiquitousKeyValueStore.default
        store.set(value, forKey: key)
        store.synchronize()
    }

    func getDataFromiCloud(key: String) -> String? {
        let store = NSUbiquitousKeyValueStore.default
        return store.string(forKey: key)
    }
}

#Preview {
    ContentView()
}

In both targets, iCloud Key-value storage capability is enabled.

In recommendations function I try to read the data.

func recommendations() -> [AppIntentRecommendation<ConfigurationAppIntent>] {
        let descriptionFromICloud = NSUbiquitousKeyValueStore.default.string(forKey: "text")
        let intent = ConfigurationAppIntent()
        let recommendation = AppIntentRecommendation(intent: intent, description: descriptionFromICloud ?? "no data")
        return [recommendation]        
    }

Now I have two problems:

  1. the data is not synchronized between iOS and watchOS app.
  2. the data is also not available in recommendations function, I always get “no data” as widget description.

What am I doing wrong?

I would be very thankful for any support.

Data sharing between WidgetWatchExtension and watchOS/iOS app
 
 
Q