SwiftUI Core Data调用NSManagedObjectContext报unrecognized selector错误
问题原因
你遇到的错误核心是CoreData跨上下文关联对象,触发了非法操作异常,问题出在两个逻辑漏洞上:
- 你创建
ListOfTasks和Sublist对象时使用的是外部传入的moc参数,但调用保存方法时用的是PersistenceController.shared.save()无参数方法,该方法默认保存的是PersistenceController单例内部持有固定上下文,无法保证和你创建对象用的moc是同一个实例 - 分两次保存的多余操作,会提前触发上下文同步,导致刚创建的
ListOfTasks对象被同步到其他上下文,后续在原moc中创建子对象建立关联时,被CoreData判定为跨上下文操作
修复方案
1. 修改PersistenceController的save方法
新增可选上下文参数,优先保存传入的上下文,避免保存错实例:
func save(context: NSManagedObjectContext? = nil) { let contextToSave = context ?? viewContext guard contextToSave.hasChanges else { return } do { try contextToSave.save() } catch { print("CoreData保存错误: \(error.localizedDescription)") } }
2. 优化业务代码的保存逻辑
删除多余的两次保存,两个对象都配置完成后统一保存一次:
func addNewList(moc: NSManagedObjectContext, mainLists: FetchedResults<ListOfTasks>, favoriteLists: FetchedResults<ListOfTasks>) { let newList = ListOfTasks(context: moc) newList.id = UUID() newList.addedDate = addedDate newList.title = title newList.icon = icon newList.color = Color.set(stringfor: color) newList.origin_Group = origin_Group if origin_Group == nil { newList.state = ListState.list.rawValue newList.index = Int16(mainLists.count) newList.isFavorite = isFavorite newList.favoriteIndex = Int16(isFavorite ? favoriteLists.count : 0) } else { if let wrappedGroup = origin_Group { newList.state = ListState.sublist.rawValue newList.index = Int16(wrappedGroup.listsArray.count-1) newList.isFavorite = false newList.favoriteIndex = 0 } } newList.isLocked = isLocked newList.isArchived = isArchived addMainSublist(to: newList, moc: moc) // 统一保存,传入当前使用的上下文 PersistenceController.shared.save(context: moc) } func addMainSublist(to newList: ListOfTasks, moc: NSManagedObjectContext) { let mainSublist = Sublist(context: moc) mainSublist.origin_List = newList mainSublist.id = UUID() mainSublist.addedDate = Date() mainSublist.index = 0 mainSublist.title = "\(title)_MainSublist" mainSublist.isExpanded = false mainSublist.isArchived = false }
3. 确认App入口上下文注入正确
检查你在App入口注入环境的上下文确实是PersistenceController单例的viewContext,避免上下文实例不统一:
@main struct TodoApp: App { let persistenceController = PersistenceController.shared var body: some Scene { WindowGroup { HomeView() // 确认此处注入的是单例的viewContext .environment(\.managedObjectContext, persistenceController.viewContext) } } }
异常复现逻辑说明
首次操作不报错是因为此时上下文没有历史残留数据,CoreData没有检测到跨上下文的非法关联;第二次操作时上下文已有之前同步产生的对象实例,触发了CoreData的上下文隔离校验,就会抛出异常。
内容的提问来源于stack exchange,提问作者Ammar Ahmad
相关产品推荐
相关产品推荐

