SwiftUI Preview 因 Core Data 'NSInvalidArgumentException' 而崩溃
Posted
技术标签:
【中文标题】SwiftUI Preview 因 Core Data \'NSInvalidArgumentException\' 而崩溃【英文标题】:SwiftUI Preview crashes with Core Data 'NSInvalidArgumentException'SwiftUI Preview 因 Core Data 'NSInvalidArgumentException' 而崩溃 【发布时间】:2022-01-02 11:14:27 【问题描述】:我的问题是我无法使用 Canvas 预览我的应用的视图,因为我总是收到错误消息:
“由于未捕获的异常而终止应用程序 'NSInvalidArgumentException',原因:'一个 NSManagedObject 类 'App.MPG_A' 必须有一个有效的 NSEntityDescription。"
现在更详细:在我要预览的视图中,我有一个抽象类 MultiplayerGame(MPG A 或 MPG B(子类)的@Binding,而 MultiplayerGame 是 Game 的子类(下图)
评论:MultiplayerGame也是一个抽象实体(如Game)和“Class” -> “MPG B”
当我想通过在 Preview 中创建 moc 对象来预览以下类时,我的应用程序崩溃但我不知道为什么:
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,但也没有用...
这个错误一定是因为Preview和moc-Object的原因,因为代码本身会编译,其他的Views都是可见的,没有错误。
感谢您的帮助!
【问题讨论】:
你是怎么得到这张图表的?是定制的解释吗? @swiftPunk 是的,它是为解释而定制的,但是当您更改下方的“编辑器样式”时,您也可以在核心数据库中获得一个 这能回答你的问题吗? PreviewProvider and ObservedObject properties 【参考方案1】:由于我尝试了所有其他可能性但没有任何帮助,因此我创建了一个新项目并检查了CoreData
。
然后我在CoreData
文件中创建了主类,并将"ContentView"
中的Item
替换为Game
。
同样在PersistenceController
中,我用Game
替换了var preview : PersistenceController
下的Item
,并使用codegen "Manual/None"
创建了所有类。
现在一切正常。
【讨论】:
【参考方案2】:您需要为您的上下文设置一个堆栈。 NSManagedObjectContext
必须知道您的模型。
以下StackBuilder
类提供了适合预览的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)
【讨论】:
我必须在任何地方调用 StackBuilder 类吗?出现相同的错误“NSInvalidArgumentException” - 但项目构建正确,其他视图可见 我是否必须只为“MPG A”之类的模型名称或“MPG A+CoreDataClass”和属性这样做?以上是关于SwiftUI Preview 因 Core Data 'NSInvalidArgumentException' 而崩溃的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI:在 Preview Provider 中执行函数
为啥 macOS 中的 SwiftUI 多行换行文本在 Preview 中有效,但在实际应用中无效?