从Share Extension执行SwiftData插入时触发EXC_BAD_ACCESS错误
问题根源
你的代码中没有为SwiftData指定App Group共享存储路径,导致主App和Share Extension各自使用独立的数据库实例。Extension环境下默认的存储路径可能存在权限限制,或者插入操作时因数据库锁、跨容器访问冲突引发卡顿和内存错误(EXC_BAD_ACCESS)。另外,你在保存操作未完成时就调用completeRequest,可能导致Extension被系统提前终止,加剧了崩溃风险。
解决方案
1. 修改ModelContainer配置,指定共享存储路径
更新ConfigureModelContainer方法,将数据库存储到App Group的共享目录中,确保主App和Extension访问同一数据库:
public func ConfigureModelContainer() -> ModelContainer { let schema = Schema([Yerl.self, Category.self]) // 替换为你的App Group ID(在开发者后台和Xcode Capabilities中配置) guard let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.yourapp.id") else { fatalError("无法获取App Group共享容器") } // 指定数据库文件路径 let storeURL = appGroupURL.appending(path: "SharedDataModel.sqlite") let modelConfiguration = ModelConfiguration( schema: schema, url: storeURL, isStoredInMemoryOnly: false ) do { return try ModelContainer(for: schema, configurations: [modelConfiguration]) } catch { fatalError("初始化ModelContainer失败: \(error.localizedDescription)") } }
2. 调整SaveAction逻辑,等待保存完成后再结束Extension
确保SwiftData的保存操作完成后,再调用completeRequest,避免系统提前终止Extension进程:
private func saveAction() { let container = ConfigureModelContainer() let modelContext = ModelContext(container) guard let defaultCategory = getDefaultCategory(container: container) else { context.completeRequest(returningItems: []) return } let foo = Foo(name: text, note: "", url: url, category: defaultCategory) modelContext.insert(foo) do { try modelContext.save() print("数据保存成功") } catch { print("保存失败: \(error.localizedDescription)") } // 确保保存操作完成后再结束请求 context.completeRequest(returningItems: []) }
3. 额外检查项
- 确认主App和Share Extension的Capabilities中都开启了App Groups,并添加了相同的Group ID
- 检查所有模型类(
Yerl、Category、Foo)的@Model标记和关系配置,避免循环引用或字段类型不匹配 - 确保Extension的主线程未被其他阻塞操作占用,SwiftData的上下文操作尽量在主线程执行(Extension本身默认运行在主线程)
内容的提问来源于stack exchange,提问作者Spiff
相关产品推荐
相关产品推荐

