Core data 如何使用SwiftUI在模式视图中创建NSManagedObject?

Core data 如何使用SwiftUI在模式视图中创建NSManagedObject?,core-data,swiftui,nsmanagedobjectcontext,Core Data,Swiftui,Nsmanagedobjectcontext,如何使用SwiftUI在模式视图中创建新的ManagedObject(MO) 遇到一个奇怪的错误,Xcode会消耗GB的内存,并通过交换文件填满mac上的硬盘 在.sheet修改器中创建模式视图时,似乎创建了某种无限循环,将注入该模式视图的ManagedObject的副本填充内存 这个示例项目至少说明了问题的一部分。如果运行它,您会看到在.sheet修改器中调用的方法会一次又一次地激发。一种理论是,下面显示ManagedObject列表的屏幕会在两个屏幕之间产生某种循环 希望在模式屏幕中使用c

如何使用SwiftUI在模式视图中创建新的ManagedObject(MO)

遇到一个奇怪的错误,Xcode会消耗GB的内存,并通过交换文件填满mac上的硬盘

.sheet
修改器中创建模式视图时,似乎创建了某种无限循环,将注入该模式视图的ManagedObject的副本填充内存

这个示例项目至少说明了问题的一部分。如果运行它,您会看到在.sheet修改器中调用的方法会一次又一次地激发。一种理论是,下面显示ManagedObject列表的屏幕会在两个屏幕之间产生某种循环

希望在模式屏幕中使用childContext,因此如果在不保存childContext的情况下取消模式视图,则将放弃任何未保存的更改。但首先需要清除这一障碍,在跨上下文共享ManagedObject方面存在一些挑战

导入核心数据
导入快捷键
结构CrtFdsUI:视图
{
@环境(\.managedObjectContext)变量moc
@FetchRequest(实体:CrtFd.entity(),SortDescriptor:[NSSortDescriptor(键路径:\CrtFd.scale,升序:true)])
var crtFds:FetchedResults
@状态变量showmodel=false
@观测对象变量absFd:absFd
func crtFdModal()->CrtFdUI{
打印(“func crtFdModal()->CrtFdUI”)
设cF=CrtFd(比例:1.0,absFd:absFd,moc:moc)
返回CrtFdUI(crtFd:cF)
}
var body:一些观点{
导航视图{
VStack{
名单{
ForEach(self.crtFds,id:\.objectID){
CrtFdCell(crtFd:$0)
}
}
.navigationBarTitle(“CrtFdsUI”)
.navigationBarItems(尾部:PlusBtn(showmodel:$showmodel))
}
.sheet(isPresented:$showmodel){self.crtfdmodel()}//FIXME:在无限循环中调用?
}
}
}
下面是ManagedObject的列表

导入核心数据
导入快捷键
结构CrtFdsUI:视图
{
@环境(\.managedObjectContext)变量moc
@FetchRequest(实体:CrtFd.entity(),SortDescriptor:[NSSortDescriptor(键路径:\CrtFd.scale,升序:true)])
var crtFds:FetchedResults
@状态变量showmodel=false
@观测对象变量absFd:absFd
func crtFdModal()->CrtFdUI{
打印(“func crtFdModal()->CrtFdUI”)
设cF=CrtFd(比例:1.0,absFd:absFd,moc:moc)
返回CrtFdUI(crtFd:cF)
}
var body:一些观点{
导航视图{
VStack{
名单{
ForEach(self.crtFds,id:\.objectID){
CrtFdCell(crtFd:$0)
}
}
.navigationBarTitle(“CrtFdsUI”)
.navigationBarItems(尾部:PlusBtn(showmodel:$showmodel))
}
.sheet(显示:$showModal){self.crtFdModal()}
}
}
}

现在,每次重新计算视图层次结构时,代码都会创建一个新的
CrtFd实例。这可能不是一个好主意,因为层次结构可能会因为您无法直接控制的原因而意外地重新计算,因此即使没有无限的创建循环,您也可能最终得到比您想要的更多的新托管对象

我下载了您的项目,我不确定这两个核心数据实体代表什么,但我注意到当
CrtFdsUI
第一次出现时,它的
absFd
已经有了
crtFd
属性的值,
crtFd
属性是一个而不是多个。这意味着,当您在此代码中创建一个新实例时,您将用一个完全相同的实例替换一个
CrtFd

我猜您并不是真的想用相同的副本替换一个实例,因此,避免问题的一种方法是将
crtFdModal()
更改为使用已经存在的副本,并且仅在没有副本的情况下创建新副本:

func crtFdModal() -> CrtFdUI {
    print("func crtFdModal() -> CrtFdUI \(showModal)")
    let cF = absFd.crtFd ?? CrtFd(scale: 1.0, absFd: absFd, moc: moc)
    return CrtFdUI(crtFd: cF)
}

这样就避免了你所描述的问题。很难说它是否正是您所需要的,但由于您的代码创建了明显不必要的重复项,因此很可能是这样。

现在,每次重新计算视图层次结构时,代码都会创建一个新的
CrtFd实例。这可能不是一个好主意,因为层次结构可能会因为您无法直接控制的原因而意外地重新计算,因此即使没有无限的创建循环,您也可能最终得到比您想要的更多的新托管对象

我下载了您的项目,我不确定这两个核心数据实体代表什么,但我注意到当
CrtFdsUI
第一次出现时,它的
absFd
已经有了
crtFd
属性的值,
crtFd
属性是一个而不是多个。这意味着,当您在此代码中创建一个新实例时,您将用一个完全相同的实例替换一个
CrtFd

我猜您并不是真的想用相同的副本替换一个实例,因此,避免问题的一种方法是将
crtFdModal()
更改为使用已经存在的副本,并且仅在没有副本的情况下创建新副本:

func crtFdModal() -> CrtFdUI {
    print("func crtFdModal() -> CrtFdUI \(showModal)")
    let cF = absFd.crtFd ?? CrtFd(scale: 1.0, absFd: absFd, moc: moc)
    return CrtFdUI(crtFd: cF)
}

这样就避免了你所描述的问题。很难说它是否正是您所需要的,但由于您的代码显然创建了不必要的重复项,因此很可能是这样。

很抱歉,这让人困惑。这是一个示例项目,因为我不知道问题出在哪里。把CrtFd想象成一种你吃的食物(100克萝卜)。AbsFd是食物的概念(1 x 100g萝卜含有大量相关营养素,如图等)。所以当你创建一个