SwiftUI Preview 与 Core Data 崩溃 'NSInvalidArgumentException'

SwiftUI Preview crashes with Core Data 'NSInvalidArgumentException'

我无法使用 Canvas 预览应用程序的视图,因为我总是收到错误消息:

"Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'An NSManagedObject of class 'App.MPG_A' must have a valid NSEntityDescription."

现在更详细:在我想预览的视图中,我有一个抽象的@Binding class MultiplayerGame (MPG A or MPG B (subclasses) MultiplayerGame 是一个subclass of Game (下图)

评论:MultiplayerGame也是一个抽象实体(和Game一样)和“Class”->“MPG B”

当我想通过在预览中创建一个 moc 对象来预览 class 以下 class 时,我的应用程序崩溃了,但我不知道为什么:

    import SwiftUI
import CoreData
import Combine

struct StandingEditView: View {
    
    //multiplayer game with MPG A or MPG B class
    @Binding var game : MultiplayerGame
    
    @State private var invokeFunction : Bool = false
    
    var body: some View {
        
        VStack{
            
            List{
                
                ForEach(game.players!, id: \.self){ player in
                    
                    HStack{
                        Text("\(player.name)")
                    }
                    
                }
                
            }
            
            Button(action: {
                invokeFunction.toggle()
            }, label: {
                Text("Button")
            })
            
        }
        
    }
}

struct StandingEditView_Previews: PreviewProvider {
    
    static let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    
    static var previews: some View {
        
        let game : MultiplayerGame = Standing(context: moc)
        
        let p1 : Player = Player(context: moc)
        let p2 : Player = Player(context: moc)
        let p3 : Player = Player(context: moc)
        
        p1.name =  "Player One"
        p2.name =  "Player Two"
        p3.name =  "Player Three"
        
        game.players = [p1,p2,p3]
        
        return StandingEditView(game: .constant(game))
    }
}

Player 的唯一(非默认)属性是 -> var name : String

我也试过使用 AppDelegate,但也没用...

错误一定是因为预览和 moc-Object 而发生的,因为代码本身编译并且其他视图是可见的而没有错误。

感谢您的帮助!

您需要为上下文设置堆栈。 NSManagedObjectContext 一定知道你的型号。

以下StackBuilderclass提供temporary版本适合预览。

private final class StackBuilder {
    
    private let modelName = "Model" // must match your model filename
    
    public enum Configuration {
        case temporary
        case permanent
    }
    
    let configuration: Configuration
    
    public init(_ configuration: Configuration = .permanent) {
        self.configuration = configuration
    }
    
    public func load() throws -> NSPersistentContainer {
        var errors = [Error]()
        let persistentContainer = NSPersistentContainer(name: modelName)
        persistentContainer.persistentStoreDescriptions = [description(for: configuration)]
        persistentContainer.loadPersistentStores { (value, error) in
            if error != nil {
                errors.append(error!)
            }
        }
        if errors.count > 0 {
            throw errors.first!
        }
        return persistentContainer as NSPersistentContainer
    }
    
    private func description(for configuration: Configuration) -> NSPersistentStoreDescription {
        let desc = NSPersistentStoreDescription(url: NSPersistentContainer.defaultDirectoryURL())
        switch configuration {
        case .temporary:
            desc.type = NSInMemoryStoreType
        case .permanent:
            desc.shouldInferMappingModelAutomatically = true
            desc.shouldMigrateStoreAutomatically = true
            desc.type = NSSQLiteStoreType
        }
        return desc
    }
}

可能需要将上下文作为环境对象传递。

static var previews: some View {
    return StandingEditView(game: .constant(game))
            .environment(\.managedObjectContext, moc)
}

由于我已经尝试了所有其他可能性,但没有任何帮助,我创建了一个新项目并检查了 CoreData

然后我在 CoreData 文件中创建了主要的 class 并在 "ContentView".

中用 Game 替换了 Item

同样在 PersistenceController 中,我将 var preview : PersistenceController 下的 Item 替换为 Game,并使用 codegen "Manual/None" 创建了所有 classes .

现在一切正常。