Updates to data from App Intent don't trigger view refresh in app

Hi all, I'm working on a really basic counter app as a way to explore SwiftData and have come across some behavior that I don't understand. I have a very simple App Intent that increments a user-specified counter in my app. The intent doesn't throw any errors and correctly updates the CoreData store but, when I switch back to my app from the Shortcuts app (where I'm testing the app intent), the view hasn't updated. Closing and re-opening the app shows the incremented counter value but I'd like to know if it's possible to have my app's UI update when the CoreData store is updated from outside the app without relaunching the whole app.

For some brief context, here's my view and the App Intent:

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
    @Query private var counters: [Counter]
    // ...
    var body: some View {
        NavigationStack {
            List {
                ForEach(counters) { counter in
                    CounterRowItem(counter: counter)
                }
                .onDelete(perform: deleteItems)
            }
            // ...
        }
    }
struct IncrementCounterIntent: AppIntent {
    static var title: LocalizedStringResource = "Increment Counter"
    @Parameter(title: "Name", optionsProvider: CounterOptionsProvider()) var name: String

    func perform() async throws -> some IntentResult & ReturnsValue<Int> {
        let provider = try CounterProvider()
        guard let counter = try provider.fetchCounters().first(where: { $0.name == name }) else {
            print("Couldn't find counter with name '\(name)'")
            return .result(value: 0)
        }

        counter.count += 1
        try provider.context.save()
        return .result(value: counter.count)
    }

    private final class CounterOptionsProvider: DynamicOptionsProvider {
        func results() async throws -> [String] {
            try CounterProvider().fetchCounters().map { $0.name }
        }
    }
}
Post not yet marked as solved Up vote post of jhearst Down vote post of jhearst
913 views
  • having the same issue and there is another post stating the same. I think its a bug and we will have to wait for GM to hopefully resolve

Add a Comment

Replies

issue still present in GM sadly

Does anyone have a Feedback number for this issue, or a workaround?

It's been 4 months and I still have this issue. Any workarounds?

After playing around with this quite a bit, it seems to be an issue only in the Simulator. Try running the app on your iPhone. That worked for me. After a couple of seconds, the data updated with the new item. This was the case in two different apps I'm working on.

Running the app on a physical device didn't solve it for me. Looks like there is a workaround here: https://github.com/JuniperPhoton/Widget-Intermediate-Animation/issues/1. I'm unable to get the separate model context to work with the @Query though, so in my case I'd have to abandon @Query which adds a lot of code to make sure the view responds to updates from different screens in the app.

I found a nasty workaround, posted it here https://github.com/JuniperPhoton/Widget-Intermediate-Animation/issues/1. Long story short – updating a SwiftData object that (might have) changed will force SwiftData to pull the other updates to this object. So what I did was the following:

.onChange(of: scenePhase) { _, newValue in
  if case .active = newValue {
    items.forEach { $0.title = $0.title }
  }
}