iOS屏幕时间应用中ShieldConfigurationExtension使用SwiftData读取主应用数据的权限问题
我之前做类似的屏幕时间应用时,也踩过这个一模一样的坑!ShieldConfigurationExtension的沙盒隔离确实严格,虽然你已经配了App Group、UserDefaults也能正常共享,但SwiftData默认的存储路径是主应用的私有沙盒目录,扩展根本没有访问权限,这就是你看到权限报错的核心原因。
给你几个亲测有效的解决思路:
强制SwiftData把数据库存在App Group共享容器
初始化ModelContainer的时候,不能用默认的路径,得手动指定到App Group的共享目录里。代码大概是这样的:// 替换成你自己的App Group ID let appGroupIdentifier = "group.com.yourcompany.yourapp" guard let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroupIdentifier) else { fatalError("无法获取App Group共享容器路径") } // 配置SwiftData的存储路径到共享容器 let modelConfig = ModelConfiguration(for: YourDataModel.self, url: sharedContainerURL.appending(path: "SharedScreenTimeData.sqlite")) // 用自定义配置初始化容器 let container = try ModelContainer(for: YourDataModel.self, configurations: modelConfig)主应用和扩展都得用这个自定义配置来初始化ModelContainer,这样两者就能访问同一个数据库文件了。
double-check App Group的配置细节
别光在Xcode的Signing & Capabilities里勾选App Group,还要去主应用和扩展的Info.plist里确认:com.apple.security.application-groups数组里都包含了你的App Group ID,缺一个都不行。另外,有时候开发者账号的App Group权限需要等一会儿才能同步,要是配置完还是报错,不妨重启Xcode或者重新选一下开发者证书。避开默认初始化的坑
很多人图省事用try ModelContainer(for: YourDataModel.self)这种默认初始化方法,它会自动把数据库存在主应用的私有Application Support目录下,扩展完全碰不到这个目录,所以一定要手动指定共享路径,别偷懒。
还有个小提醒:如果你的SwiftData模型需要做版本迁移,主应用和扩展的模型版本必须完全一致,不然一边迁移了数据库结构,另一边还在用旧模型,也会出现读取失败或者权限相关的报错。
内容来源于stack exchange

