使用CoreData预览ContentView

key*_*ogg 7 core-data swiftui

当我尝试包含CoreData提取请求的SwiftUI ContentView时,预览崩溃。想知道设置@environment的正确方法是什么,以便预览可以访问coredata堆栈。当构建模拟器但不使用PreviewProvider时,此方法工作正常

import SwiftUI

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

    @FetchRequest(entity: ProgrammingLanguage.entity(), sortDescriptors: [
            NSSortDescriptor(keyPath: \ProgrammingLanguage.name, ascending: true),
            NSSortDescriptor(keyPath: \ProgrammingLanguage.creator, ascending: false)
        ]) var languages: FetchedResults<ProgrammingLanguage>

    var body: some View {
        NavigationView {
            List {
                ForEach(languages, id: \.self) { language in
                    Text("Language: \(language.name ?? "Anonymous")")
                }
            }
            .navigationBarTitle("My Languages")
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
Run Code Online (Sandbox Code Playgroud)

当我尝试将参数传递给ContentView_Previews中的ContentView时,出现以下编译器错误。

ContentView(managedObjectContext: managedObjectContext)
Run Code Online (Sandbox Code Playgroud)

错误:实例成员'managedObjectContext'不能用于类型'ContentView_Previews'

SwiftUI预览可能不支持此功能吗?还是有什么可以解决这个问题?

我正在运行Xcode 11 Beta 7。

bjn*_*ier 9

感谢@ShadowDES-在Xcode Beta 7的Master / Detail模板项目中,有一个使用Core Data的预览:

#if DEBUG
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView().environment(\.managedObjectContext, context)
    }
}
#endif
Run Code Online (Sandbox Code Playgroud)

这在Xcode Beta 5中对我有效(我的Beta 7崩溃)

  • 那会从持久存储中加载数据吗? (2认同)

Chu*_*k H 5

接受的答案对我不起作用。

问题的本质是预览似乎从它自己的(空的!)持久存储开始,因此您必须以某种方式用足够的对象填充该存储以使所有预览都能工作。我创建了一个类函数,如果数据库为空,它会用示例对象填充数据库。此外,对于模型中的每个实体,我创建了一个静态属性,该属性返回这些示例对象之一,根据需要作为参数传递给正在预览的特定视图。

如果预览使用大量托管对象,这会简化预览代码:

struct StringAttributeView_Previews: PreviewProvider {  
    static var previews: some View {
        Preview.database()
        return NavigationView {
            StringAttributeView(attribute: Preview.attribute)
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的预览类的编辑示例。显然,它是特定于我的 DataModel 类的,并且必须根据您独特的数据模型进行定制,但它应该让您了解需要什么。

class Preview {

    //MARK: - Populate Preview's Core Data Database
    class func database() {
        if DataModel.isDatabaseEmpty() {
            McDocument.loadSampleData()
        }
    }

    //MARK: - For Previews
    class var attribute:
        Attribute { get { return DataModel.allObjects(for: "Attribute").first as! Attribute } }
}
Run Code Online (Sandbox Code Playgroud)