在 SwiftUI 和 Core Data 中链接多个实体

问题描述

我有一个非常简单的应用程序,您应该可以在其中存储电影院、电影和演员。我首先使用非持久存储创建了它,以便我可以测试一切是否运行良好。

import SwiftUI
import CoreData

struct ContentView: View {
    @Environment(\.managedobjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Cinema.name,ascending: true)],animation: .default)
    private var items: FetchedResults<Cinema>
    
    @State var showCinemaSheet = false
    
    @State var cinemas = [CinemaDummy]()

    var body: some View {
        vstack {
            Button("Create New Cinema") {
                showCinemaSheet.toggle()
            }.sheet(
                isPresented: $showCinemaSheet,content: {
                NewCinemaSheetView(
                    showCinemaSheet: $showCinemaSheet,cinemas: $cinemas)
            })
            Divider()
            Text("List of Cinemas")
            List {
                ForEach(cinemas) { cinema in
                    vstack(alignment: .leading) {
                        HStack {
                            Text(cinema.name).font(.headline)
                            Spacer()
                            Text(cinema.location).font(.headline)
                        }
                        Text("\(cinema.movies.count) Movies")
                    }
                    
                }
            }
        }
    }
}

struct NewCinemaSheetView: View {
    @Binding var showCinemaSheet: Bool
    @Binding var cinemas: [CinemaDummy]
    @State var cinemaDummy = CinemaDummy()
    @State var showMovieSheet = false
    
    
    var body: some View {
        vstack {
            
            
            Button("Add new movie"){
                showMovieSheet.toggle()
            }.sheet(isPresented: $showMovieSheet,content: {
                NewMovieSheetView(showMovieSheet: $showMovieSheet,movies: $cinemaDummy.movies)
            })
            
            TextField("Enter name of the cinema",text: $cinemaDummy.name).padding().border(Color.black,width: 1)
            TextField("Enter location of the cinema",text: $cinemaDummy.location).padding().border(Color.black,width: 1)
            Divider()
            Text("List of movies")
            List{
                ForEach(cinemaDummy.movies) { movie in
                    vstack {
                        Text(movie.title)
                        Text("\(movie.actors.count) Actors")
                    }
                }
                
            }
            
            Divider()
            
            HStack {
                Button("Save") {
                    cinemas.append(cinemaDummy)
                    showCinemaSheet.toggle()
                }.padding()
                Button("Cancel") {
                    showCinemaSheet.toggle()
                }.padding()
            }
        }
    }
}

struct NewMovieSheetView: View {
    @Binding var showMovieSheet: Bool
    @Binding var movies: [MovieDummy]
    @State var showActorSheet = false
    @State var movieDummy = MovieDummy()
    
    var body: some View {
        vstack {
            Button("Add New Actor") {
                showActorSheet.toggle()
            }.sheet(isPresented: $showActorSheet,content: {ActorViewSheetView(
                        showActorSheet: $showActorSheet,actors: $movieDummy.actors
                    )})
            TextField("Enter tile of movie",text: $movieDummy.title).padding().border(Color.black,width: 1)
            TextField("Enter budget of movie",text: $movieDummy.budget).padding().border(Color.black,width: 1)
            Divider()
            Text("list of actors in this movie")
            List{
                ForEach(movieDummy.actors) { actor in
                    HStack {
                        Text(actor.firstName)
                        Text(actor.lastName)
                    }
                }
            }
            
            Divider()
            HStack {
                Button("Add") {
                    movies.append(movieDummy)
                    showMovieSheet.toggle()
                }.padding()
                Button("Cancel") {
                    showMovieSheet.toggle()
                }.padding()
            }
        }
    }
}

struct ActorViewSheetView: View {
    @Binding var showActorSheet: Bool
    @Binding var actors: [ActorDummy]
    @State var actorDummy = ActorDummy()
    
    
    var body: some View {
        vstack {
            TextField("Enter first name of actor",text: $actorDummy.firstName)
                .padding()
                .border(Color.black,width: 1)
            TextField("Enter last name of actor",text: $actorDummy.lastName)
                .padding()
                .border(Color.black,width: 1)
            Divider()

            
            Divider()
            HStack {
                Button("Add") {
                    actors.append(actorDummy)
                    showActorSheet.toggle()
                }.padding()
                Button("Cancel") {
                    showActorSheet.toggle()
                }.padding()
            }
        }
    }
}

这些是创建的模型:

import Foundation
struct CinemaDummy: Identifiable {
    var id = UUID()
    var name = ""
    var location = ""
    var movies = [MovieDummy]()
}

struct MovieDummy: Identifiable {
    var id = UUID()
    var title = ""
    var budget = ""
    var actors = [ActorDummy]()
}

struct ActorDummy: Identifiable {
    var id = UUID()
    var firstName = ""
    var lastName = ""
}

现在我想保护数据持久化,但我无法做到这一点。我尝试在 xcdatamodeld 中创建模型,然后尝试通过彼此链接关系。

enter image description here

enter image description here

enter image description here

enter image description here

起初我想让 Xcode 为我完成所有工作,并让 Codegen 在“类定义”上工作,但它不起作用。 我通过“手动”设置 Codegen 并尝试添加处理 NSSet 的方法。 我通过(xcdatamodeld 中的所有选定模型)编辑器创建的文件 -> 创建 NSManagedobject Sublass 但这也不能运行。

在将近两周的时间里,我花了几天时间将这个项目连接到 CoreData,但没有任何帮助。

Persistence-manager 几乎是开箱即用的 Xcode-Manager:

import CoreData

struct PersistenceController {
    static let shared = PersistenceController()

    static var preview: PersistenceController = {
        let result = PersistenceController(inMemory: true)
        let viewContext = result.container.viewContext

        do {
            try viewContext.save()
        } catch {
            let nsError = error as NSError
            fatalError("Unresolved error \(nsError),\(nsError.userInfo)")
        }
        return result
    }()

    let container: NSPersistentContainer

    init(inMemory: Bool = false) {
        container = NSPersistentContainer(name: "Cinematic")
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.loadPersistentStores(completionHandler: { (storeDescription,error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error),\(error.userInfo)")
            }
        })
    }
}

我的问题是: - 有没有办法将这个项目连接到 CoreData? - 我可以通过“类定义”设置 Codegen 还是我必须手动完成所有这些工作? - 如何处理 NSSet?

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)