core-data - 使用SwiftUI、Core Data、一对多关系,为什么在Many端添加一行时列表没有更新

标签 core-data swiftui relationship

我有一个带有 Core Data 的 SwiftUI 项目。数据模型是一个简单的一对多和两个主 View ,每个 View 顶部都有一个文本字段,还有一个按钮,用于向下面的 ListView 添加新项目。第一个 View 是针对关系的一方,第二个是针对多方。因此,第一个中的 NavigationLink 打开第二个并传递 One 对象。看起来很标准的东西。创建 One 的方法有效,当托管对象上下文保存新项目时,下面的列表会立即更新。但是,在设备上查看时,相同类型的方法不会刷新多方的列表,尽管它在模拟器和预览窗口中运行良好。数据肯定会被保存,因为如果您导航回一侧然后重新选择它以重新加载许多 View ,它会在列表中显示新项目。

我浏览了很多教程、其他问题等,但没有找到原因。我在如何进入关系的多方面做错了什么,还是我必须做其他事情来刷新多方面的 View ?谢谢!!!

完整项目可在 https://github.com/fahrsoft/OneToManyTest

从 ContentView 中,显示一侧(注意:OneView 是一个简单的 View ,它接受对象并显示文本。ManyView 也是如此。):

struct ContentView: View {
@Environment(\.managedObjectContext) var moc
@FetchRequest(entity: One.entity(), sortDescriptors: []) var ones: FetchedResults<One>

@State private var newName = ""
@State var isNavTitleHidden = true

var body: some View {
    NavigationView {
        VStack {
            HStack {
                TextField("New One", text: self.$newName)
                Spacer()
                Button(action: {
                    let newOne = One(context: self.moc)
                    newOne.name = self.newName
                    self.newName = ""
                    try? self.moc.save()
                }) {
                    Image(systemName: "plus.circle.fill")
                        .foregroundColor(.green)
                        .frame(width: 32, height: 32, alignment: .center)
                }
            }
            .padding(.top)
            .padding(.horizontal)

            List {
                Section(header: Text("Ones")) {
                    ForEach(self.ones, id:\.self) { (one:One) in
                        NavigationLink(destination: OneDetailView(one: one, isNavTitleHidden: self.$isNavTitleHidden).environment(\.managedObjectContext, self.moc)) {
                            OneView(one: one).environment(\.managedObjectContext, self.moc)
                        }
                    }

                    .onDelete { indexSet in
                        let deleteOne = self.ones[indexSet.first!]
                        self.moc.delete(deleteOne)
                        do {
                            try self.moc.save()
                        } catch {
                            print(error)
                        }
                    }
                }
            }
        }
        .navigationBarTitle(Text("Ones List"))
        .navigationBarHidden(self.isNavTitleHidden)
        .onAppear {
            self.isNavTitleHidden = true
        }
    }
}}

从 OneDetailView 显示多方面:
struct OneDetailView: View {
@Environment(\.managedObjectContext) var moc

@ObservedObject var one: One

@State private var newManyAttribute = ""
@Binding var isNavTitleHidden: Bool

var body: some View {
    VStack {
        HStack {
            TextField("New Many", text: self.$newManyAttribute)
            Spacer()
            Button(action: {
                let newMany = Many(context: self.moc)
                newMany.attribute = self.newManyAttribute
                self.newManyAttribute = ""
                self.one.addToMany(newMany)
                try? self.moc.save()
            }) {
                Image(systemName: "plus.circle.fill")
                    .foregroundColor(.green)
                    .frame(width: 32, height: 32, alignment: .center)
            }
        }
        .padding(.top)
        .padding(.horizontal)

        List {
            Section(header: Text("Manys")) {
                ForEach(self.one.manyArray, id: \.self) { many in
                    ManyView(many: many).environment(\.managedObjectContext, self.moc)
                }
            }
        }
    }
    .navigationBarTitle("\(self.one.wrappedName) Details")
    .onAppear {
        self.isNavTitleHidden = false
    }
}}

最佳答案

我能想出的唯一方法是使用谓词中的选定 One 为 Many 项目创建一个新的 FetchRequest。将 FetchRequest 和 init 添加到 OneDetailView 的开头允许列表更新。

struct OneDetailView: View {
@Environment(\.managedObjectContext) var moc

@ObservedObject var one: One

@State private var newManyAttribute = ""
@Binding var isNavTitleHidden: Bool

@FetchRequest var manys: FetchedResults<Many>

init(one: One, isNavTitleHidden: Binding<Bool>) {
    self.one = one
    self._isNavTitleHidden = isNavTitleHidden
    var predicate: NSPredicate?
    predicate = NSPredicate(format: "one = %@", one)
    self._manys = FetchRequest(
        entity: Many.entity(),
        sortDescriptors: [],
        predicate: predicate
    )
}

var body: some View {
    VStack {
        HStack {
            TextField("New Many", text: self.$newManyAttribute)
            Spacer()
            Button(action: {
                let newMany = Many(context: self.moc)
                newMany.attribute = self.newManyAttribute
                self.newManyAttribute = ""
                self.one.addToMany(newMany)
                try? self.moc.save()
            }) {
                Image(systemName: "plus.circle.fill")
                    .foregroundColor(.green)
                    .frame(width: 32, height: 32, alignment: .center)
            }
        }
        .padding(.top)
        .padding(.horizontal)

        List {
            Section(header: Text("Manys")) {
                ForEach(self.manys, id: \.self) { many in
                    ManyView(many: many).environment(\.managedObjectContext, self.moc)
                }
            }
        }
    }
    .navigationBarTitle("\(self.one.wrappedName) Details")
    .onAppear {
        self.isNavTitleHidden = false
    }
}}

关于core-data - 使用SwiftUI、Core Data、一对多关系,为什么在Many端添加一行时列表没有更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60938772/

相关文章:

swift - 在 Swift 核心数据应用程序中的哪里添加 `addPersistentStoreWithType:configuration:URL:options:error:`?

swiftui - 在 SwiftUI 范围内找不到该类

ios - 自定义字体未在 SwiftUI 中显示

php - 可捕获的 fatal error : Object of class Proxies\__CG__\AppBundle\Entity\Ticket could not be converted to string

php - Laravel 属于ToMany 关系条件

ios - 如何最好地构建代码以在 iOS 中使用 AFNetworking 和 CoreData 下载资源

swift - 文本与应删除的文本重叠

swift - 在哪里放置更新核心数据函数(swift)

generics - SwiftUI 通用上下文菜单 View

ruby-on-rails - Rails has_many :through association