Skip to main content
✨ Run your entire business in one platform — CRM, HR, Accounting, Projects & more. Start Free Trial →

Why @FetchRequest Doesn't Work with Share Extensions (And What Does)

Why @FetchRequest Doesn't Work with Share Extensions (And What Does)
By: Dev.to Top Posted On: March 24, 2026 View: 6
If you've built an iOS Share Extension that writes to a shared Core Data store, you've probably hit this wall: the data saves fine, but your main app's SwiftUI list doesn't update until you kill and relaunch it. I hit this while building a bookmarking app during a live stream. I was using Claude Code to build the whole thing. Got the Share Extension working, got it saving to Core Data through an App Group, deployed to my phone, shared a YouTube link, and... the app just sat there showing the old data. Kill the app, relaunch, there it is. Cool. Very helpful. I spent the next few hours figuring out why, and I'm writing it up so you don't have to. The Setup Nothing exotic going on here. A main app and a Share Extension both access the same Core Data SQLite store through an App Group container: Main App ←→ App Group Container (ShareSaver.sqlite) ←→ Share Extension Both targets share a PersistenceController that points the persistent store at the App Group path: class PersistenceController static let shared = PersistenceController() let container: NSPersistentContainer private static let appGroupID = "group.com.example.ShareSaver" init(inMemory: Bool = false) container = NSPersistentContainer(name: "ShareSaver") if let storeURL = FileManager.default .containerURL(forSecurityApplicationGroupIdentifier: Self.appGroupID)? .appendingPathComponent("ShareSaver.sqlite") container.persistentStoreDescriptions.first!.url = storeURL container.loadPersistentStores _, error in if let error fatalError("Store failed: \(error)") container.viewContext.automaticallyMergesChangesFromParent = true The Share Extension saves items using a background context: private func saveItem(text: String) let context = PersistenceController.shared.container.newBackgroundContext() context.performAndWait let item = SavedItem(context: context) item.id = UUID() item.text = text item.createdAt = Date() try? context.save() This all works fine. The data lands in SQLite. Kill the app, relaunch, the data shows up, so it's definitely being persisted. The problem is getting the main app to see that data without a relaunch. Quick sidebar on why I went with Core Data instead of SwiftData: I was using Claude Code to build this project, and AI coding tools just aren't trained well enough on SwiftData yet. There's not enough content out there for them to do a great job with it. Plus SwiftData hasn't gone through the battle testing that Core Data has. So I stuck with what I know works. If you're doing agent-assisted coding, I'd honestly recommend the same. At least for now. The @FetchRequest Approach Here's what you'd write first, and what every Core Data + SwiftUI tutorial shows: struct ContentView: View @Environment(\.managedObjectContext) private var viewContext @Environment(\.scenePhase) private var scenePhase @FetchRequest( sortDescriptors: [NSSortDescriptor(keyPath: \SavedItem.createdAt, ascending: false)] ) private var items: FetchedResults var body: some View List ForEach(items) item in Text(item.text ?? "") .onChange(of: scenePhase) if scenePhase == .active viewContext.refreshAllObjects() You share a link, switch back to the app, and... nothing. The list is stale. Only a full kill-and-relaunch shows the new item. I already had a bad feeling about this when I saw @FetchRequest being used. I'll be honest; I don't love property wrappers. I think they partially ruined Swift. But what can you do ??‍♂️ Why @FetchRequest Breaks Across Processes Your Share Extension runs in a completely separate process. The extension has its own PersistenceController instance, its own NSPersistentContainer, and its own managed object context. When it calls context.save(), it writes directly to the SQLite file. The main app's viewContext has no idea that happened. @FetchRequest creates an NSFetchedResultsController under the hood that listens for NSManagedObjectContextObjectsDidChange notifications on the viewContext. Objects inserted, updated, or deleted within that context trigger the notification and SwiftUI re-renders. Cross-process writes don't trigger any of that. The Share Extension writes to SQLite, and the main app's viewContext is sitting there working with a stale in-memory cache. refreshAllObjects() doesn't help either. It re-faults every managed object currently registered in the context, but it can't discover new objects. If the Share Extension inserted a row that this context has never seen, refreshAllObjects() has nothing to refresh. The context doesn't even know the row exists. The Debugging Spiral
Share:

Tags:
#0 

Read this on Dev.to Top Header Banner

Want to run a more efficient business?

Mewayz gives you CRM, HR, Accounting, Projects & eCommerce — all in one workspace. 14-day free trial, no credit card needed.

Try Mewayz Free →

Comments

Power your business with Mewayz ERP

All-in-one platform: CRM, HR, Accounting, Project Management, eCommerce & more. 14-day free trial.

Start Your Free Trial →

No credit card required · Cancel anytime · 131+ modules

Contact Us
  Follow Us
Site Map
Get Site Map
About

Mewayz News brings you the latest breaking news, in-depth analysis, and trending stories from around the world. Covering politics, technology, business, sports, entertainment, and more — updated every hour, 24/7.

Mewayz Network

Mewayz App Stream Watch TV Music Games Tools Calculators Dictionary Books Quotes Recipes Photos Fonts Icons Study Papers Resume Templates Compare Reviews Weather Trading Docs Draw Paste Sign eBooks AI Learn Currency Convert Translate Search QR Code Timer Typing Colors Fitness Invoice Directory Social Seemless