解决在AppIntent中访问mainContext的Non-sendable类型警告
解决Widget中访问SwiftData ModelContext的Sendable警告
问题根源
警告的核心原因:
ModelContext并非Sendable类型,无法安全跨actor边界传递modelContainer.mainContext被标记为@MainActor隔离属性,直接在自定义DataModelactor外部访问会触发跨actor的不安全访问检查
最佳解决方案:封装数据操作到DataModel内部
将添加Item的逻辑封装在DataModel actor内部,避免外部直接接触ModelContext,从根源上消除跨actor传递non-sendable类型的问题。
修改DataModel代码
import SwiftUI import SwiftData actor DataModel { struct TransactionAuthor { static let widget = "widget" } static let shared = DataModel() private init() {} nonisolated lazy var modelContainer: ModelContainer = { let modelContainer: ModelContainer do { modelContainer = try ModelContainer(for: Item.self) } catch { fatalError("Failed to create the model container: \(error)") } return modelContainer }() // 封装添加Item的方法,内部处理ModelContext操作 func addNewItem() async { await MainActor.run { let newItem = Item(timestamp: Date()) self.modelContainer.mainContext.insert(newItem) // 主动保存上下文,确保数据持久化 do { try self.modelContainer.mainContext.save() } catch { print("Failed to save new item: \(error)") } } } }
修改Intent代码
import AppIntents struct AddNewItemIntent: AppIntent { static var title: LocalizedStringResource = "Add new item intent" func perform() async throws -> some IntentResult { print("AddNewItemIntent button tapped") // 调用封装好的方法,无需直接接触ModelContext await DataModel.shared.addNewItem() return .result() } }
替代方案:在主actor上下文执行操作
如果不想封装方法,可以直接在MainActor.run中执行ModelContext操作,确保访问mainContext时处于主actor环境,避免跨actor访问:
import AppIntents struct AddNewItemIntent: AppIntent { static var title: LocalizedStringResource = "Add new item intent" func perform() async throws -> some IntentResult { print("AddNewItemIntent button tapped") await MainActor.run { let newItem = Item(timestamp: Date()) DataModel.shared.modelContainer.mainContext.insert(newItem) do { try DataModel.shared.modelContainer.mainContext.save() } catch { print("Save error: \(error)") } } return .result() } }
方案说明
- 第一种方案通过封装,将所有对
ModelContext的操作限制在DataModel内部,外部只调用安全的actor方法,完全避免了跨actor传递non-sendable类型 - 第二种方案确保
mainContext的访问和操作都在主actor上下文完成,符合其@MainActor隔离的要求,消除了不安全访问的警告
两种方案都能适配Swift 6的严格Sendable检查,避免警告升级为错误。
内容的提问来源于stack exchange,提问作者appfrosch
相关产品推荐
相关产品推荐

