如何在一个应用程序中拥有多个单独的核心数据实体类型

问题描述 投票:0回答:1

我主要在 iPad 版 Swift Playgrounds 中创建应用程序,因此我实际上并没有在 XCode 上使用 Core Data 工具。在教程的帮助下,我创建了一个

PersistenceController
和一个数据模型。当我只有一种实体类型 (
Club
) 时,一切都运行良好。现在我想要一个不同的、不相关的实体(
Game
)。当我尝试在应用程序中的任何位置添加另一个
@FetchRequest
并发送错误“FetchRequest 必须有一个实体”时,我的应用程序崩溃了。我相信这是因为在我的
PersistenceController
我有

let model = NSManagedObjectModel()
        model.entities = [clubEntity]
        //model.entities = [gameEntity]

我认为我需要

model.entities = [gameEntity]’ to fix the error mentioned above, but that will override my clubEntity no? When I include the gameEntity, I get the same error, but it appears on 
@main` 而不是在 ContentView 中。我已经包含了我认为可能与该问题相关的所有代码,但我可以根据要求添加更多代码。

import SwiftUI

@main

struct MyApp: App {
    @StateObject private var locationManager = LocationManagerModel()
    let persistanceController = PersistanceController.shared
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environment(\.managedObjectContext, persistanceController.container.viewContext)
                .environmentObject(locationManager)
                .transition(AnyTransition.opacity.animation(.easeInOut(duration: 0.5)))
        }
    }
}
import SwiftUI

import CoreData

struct PersistanceController {
    static let shared = PersistanceController()
    
    static var preview: PersistanceController = {
        let result = PersistanceController(inMemory: true)
        let viewContext = result.container.viewContext
//        for index in 0..<10 {
//            
//        }
        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) {
        
        let clubEntity = NSEntityDescription()
        clubEntity.name = "Club"
        clubEntity.managedObjectClassName = "Club"
        
        let idAttribute = NSAttributeDescription()
        idAttribute.name = "id"
        idAttribute.type = .uuid
        clubEntity.properties.append(idAttribute)
        
        let nameAttribute = NSAttributeDescription()
        nameAttribute.name = "name"
        nameAttribute.type = .string
        clubEntity.properties.append(nameAttribute)
        
        let putterAttribute = NSAttributeDescription()
        putterAttribute.name = "putter"
        putterAttribute.type = .boolean
        clubEntity.properties.append(putterAttribute)
        
        let strokesNumAttribute = NSAttributeDescription()
        strokesNumAttribute.name = "strokes"
        strokesNumAttribute.type = .integer32
        clubEntity.properties.append(strokesNumAttribute)
        
        let strokesListAttribute = NSAttributeDescription()
        strokesListAttribute.name = "strokesList"
        strokesListAttribute.type = .transformable
        clubEntity.properties.append(strokesListAttribute)
        
        /////////////////////////////////
        
        let gameEntity = NSEntityDescription()
        gameEntity.name = "Game"
        gameEntity.managedObjectClassName = "Game"
        
        gameEntity.properties.append(idAttribute)
        
        gameEntity.properties.append(strokesNumAttribute)
        
        
        let model = NSManagedObjectModel()
        model.entities = [clubEntity]
        model.entities = [gameEntity]
        
        
        container = NSPersistentContainer(name: "ClubToDo", managedObjectModel: model)
        if inMemory {
            container.persistentStoreDescriptions.first!.url = URL(fileURLWithPath: "/dev/null")
        }
        container.viewContext
            .automaticallyMergesChangesFromParent = true
        container.loadPersistentStores(completionHandler: {(storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
    }
}
import SwiftUI
import CoreData
import Foundation

@objc(Game)
public class Game: NSManagedObject {
    @NSManaged public var id: UUID
    @NSManaged public var strokes: Int
}

@objc(Club)
public class Club: NSManagedObject {
    @NSManaged public var id: UUID
    @NSManaged public var name: String
    //@NSManaged public var yardsNum: Int
    @NSManaged public var strokes: Int
    @NSManaged public var putter: Bool
    @NSManaged public var strokesList: [Int]
    //@NSManaged public var averageYardage: Int
    @NSManaged public var nfcTag: String
}

extension Club: Identifiable {
//    var yards: Yards{
//        get {
//            Yards(rawValue: Int(yardsNum)) ?? .normal
//        }
//        
//        set {
//            self.yardsNum = Int(newValue.rawValue)
//        }
//    }
    var strokesStandardDeviation: Double {
        guard !strokesList.isEmpty else {
            return 0.0 // or another appropriate value when the list is empty
        }
        let mean = Double(strokesList.reduce(0, +)) / Double(strokesList.count)
        let squaredDifferences = strokesList.map { pow(Double($0) - mean, 2) }
        let variance = squaredDifferences.reduce(0, +) / Double(strokesList.count)
        return sqrt(variance)
    }
    var averageYardage: Int {
        guard !strokesList.isEmpty else {
            return 0
        }
        let numStrokes = strokesList.count
        let sumArray = strokesList.reduce(0,+)
        let averageYardage = sumArray / numStrokes
        return averageYardage
    }
}
enum Yards: Int {
    case normal = 0
}
import SwiftUI
import CoreLocation
import CoreData
import Combine

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext
    @FetchRequest(
        entity: Club.entity(),
        sortDescriptors:[])
    private var clubs:FetchedResults<Club>
    
//    @FetchRequest(
//        entity: Game.entity(),
//        sortDescriptors:[])
//    private var games:FetchedResults<Game>
    
    @State private var shotClub = Club()
    @State private var ballClub = Club()
    @State private var showNewClub: Bool = false
    @EnvironmentObject var locationManager: LocationManagerModel
    //@State private var game = ""
    @AppStorage("NUMBER_KEY") var counter = 0
    @State var roundStarted = false
    var body: some View {
        TabView{
            ClubListView(counter: $counter, roundStarted: $roundStarted)
                .tabItem {
                    Image(systemName: "list.bullet.rectangle.portrait")
                }
            RoundView(counter: $counter, roundStarted: $roundStarted)
                .tabItem {
                    Image(systemName: "flag")
                }
        }
    }
}


swiftui core-data persistence
1个回答
0
投票

model.entities
属性是一个数组,应列出模型中要使用的所有实体。正如您所注意到的,为其分配两次值是行不通的,因为第二次分配会覆盖第一次分配。您需要在一个实体数组中列出单个作业中的所有实体:

model.entities = [clubEntity, gameEntity]

看到如何在代码中设置实体而不使用 Xcode 模型编辑器是非常酷的。没有多少人这样做,而且很多人没有意识到这是可能的。

© www.soinside.com 2019 - 2024. All rights reserved.