SwiftUI PreviewProvider 使用 CoreData 显示特定的 NSManagedObject 条目

SwiftUI PreviewProvider using CoreData to show specific NSManagedObject Entry

[Xcode 12.4,Catalina 10.15.6,使用 SwiftUI 和 CoreData 的 MacOS 项目]

我正在开发一个应用程序来显示我拥有的一些数据。该应用程序的业务逻辑运行良好,现在我将注意力转向 UI。 为了整理 UI,我想让 PreviewProvider 为每个视图工作。我还希望预览显示我在 CoreData 数据存储区中已有的数据。

经过多番挫折,我终于设法让预览编译并显示,但是我在预览中看不到任何实际数据。看起来虽然 NSManagedObjectContext 在那里,但预览没有 selected 任何要显示的条目。

如何 select 说出我的数据存储中的第 3 个条目显示在预览中?

下面是我的视图代码,在末尾包含 PreviewProvider(正常情况下),后面有一些注释解释它。

    
    
    import SwiftUI
    
    struct DomainRow: View {
      
      @Environment(\.managedObjectContext) var context
      @ObservedObject var domain : DomainFiles
      private var id : LocalizedStringKey {
        get {
          return LocalizedStringKey(String(Int(domain.id)))
        }
      }
      
      var body: some View {
        HStack (alignment: .center) {
          Text(id)
          Spacer()
          VStack(alignment: .leading) {
            Text(domain.name!)
              .fontWeight(.bold)
              .truncationMode(.tail)
              .frame(minWidth: 20)
    
            Text(domain.path!)
              .font(.caption)
              .opacity(0.625)
              .truncationMode(.middle)
          }
        }
        .padding(.vertical, 4)
      }
    }
    
    #if DEBUG
    struct DomainRow_Previews: PreviewProvider {
    
      @Environment(\.managedObjectContext) var managedObjectContext
    
      static var previews: some View {
        let context = CoreDataStack.context
        let domain = DomainFiles(context: context)
        return DomainRow(domain: domain)
          .environment(\.managedObjectContext, CoreDataStack.context)
      }
    }
    #endif

DomainFiles 是一个 CoreData 实体(有几千个条目),每个实体都有几个属性,包括 idnamepath(到文件)。 CoreDataStack.context 是对下面所示结构的引用。

为了按照 PreviewProvider 的要求获得静态 NSManagedObjectContext,我已将以下结构添加到我的项目中,根据 https://developer.apple.com/forums/thread/650269

    import Foundation
    import CoreData
    
    struct CoreDataStack {
        static var context: NSManagedObjectContext {
            return persistentContainer.viewContext
        }
      
        static let containerName: String = "MyAppsDataStore"
    
        static var persistentContainer: NSPersistentContainer = {
            let container = NSPersistentContainer(name: containerName)
            container.loadPersistentStores { (description, error) in
                if let error = error {
                    print(error)
                }
            }
            return container
        }()
    //    Don't need to save anything in the preview.
    //    func saveContext() { ... }
    }

例如,我想将带有 domain.id == 3 的条目传递到预览中。 我怎样才能做到这一点? (提前感谢您的关注。)

我找出了我的 PreviewProvider 结构中缺少的东西:

  1. 我需要执行 NSFetchrequest 才能获取数据。
  2. 然后,我能够使用数组索引访问数据存储中的条目。
    请注意,索引是 CoreData 的内部表示,如果您想要特定的项目,请使用 SQLite 浏览数据存储以找到您想要查看的项目。
struct EntriesView_Previews: PreviewProvider {

  @Environment(\.managedObjectContext) var managedObjectContext

  static var previews: some View {
    let context = CoreDataStack.context
    let domainFiles : [DomainFiles]
    let requestDomainFiles : NSFetchRequest<DomainFiles> = DomainFiles.fetchRequest()
    do {
      domainFiles = try context.fetch(requestDomainFiles)
    } catch {
      let nserror = error as NSError
      fatalError("Error \(nserror): \(nserror.userInfo)")   //  DO NOT DO THIS IN REAL CODE.  PROVIDE FALLBACK
    }
    let domain = domainFiles[0]
    return EntriesView(domain: domain)
      .environment(\.managedObjectContext, CoreDataStack.context)
  }
}