使用 FetchRequest 时如何在 PreviewProvider 中显示示例数据

How to show sample data in PreviewProvider when using FetchRequest

我有一个像这样的 SwiftUI 视图:

import SwiftUI

struct ReView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(
        entity: Re.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Re.name, ascending: false)
        ]
    ) var entities: FetchedResults<Re>
    
    var body: some View {
        NavigationView {
            List(entities, id: \.self) { entity in
                Text(entity.name ?? "Unknown")
            }
        }
    }
}

struct ReView_Previews: PreviewProvider {
    static var previews: some View {
            Group {
               
                ReView()
                    .environment(\.managedObjectContext, PersistentCloudKitContainer.persistentContainer.viewContext)
            }
        }
}

如何在预览中显示一些样本数据?

我在为预览结构创建静态 moc 并根据需要向其中添加数据方面取得了一些成功。

像这样:

struct ReView_Previews: PreviewProvider {
    static let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
    _ = Re(context: moc, mandatoryParam1: "foo" ...)
    _ = Re(context: moc, mandatoryParam1: "bah" ...)
    
    static var previews: some View {
        Group {
            ReView()
                .environment(\.managedObjectContext, moc)
        }
    }
}

我对 SwiftUI 还处于早期阶段,所以几乎可以肯定有更优雅的实现方式。但是,从本质上讲,创建测试数据只是对模拟器上发生的序列进行编程以创建它,因为在实时模式下预览就是这样。

缺点是清除损坏的测试数据也需要一些编程工作。

祝你好运。

这里是适应的方法(早期在 中提出),用 Xcode 12 / iOS 14

测试

想法是将显式视图 + 模型与模型提供者(在本例中为云数据库)分开,因此可以设计和测试(预览)具有本地或动态构造的模拟模型(不涉及大量云连接)的视图

struct ReView: View {
    @Environment(\.managedObjectContext) var moc
    @FetchRequest(
        entity: Re.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Re.name, ascending: false)
        ]
    ) var entities: FetchedResults<Re>
    
    var body: some View {
        ReEntitiesView(entities: entities)
    }
}

struct ReEntitiesView<Results:RandomAccessCollection>: View where Results.Element == Re {
    let entities: Results

    var body: some View {
        NavigationView {
            List(entities, id: \.self) { entity in
                Text(entity.name ?? "Unknown")
            }
        }
    }
}

struct ReView_Previews: PreviewProvider {
    static let entity = NSManagedObjectModel.mergedModel(from: nil)?.entitiesByName["Re"]

    static var previews: some View {
       let object = Re(entity: entity!, insertInto: nil)
       object.name = "Test Name"

       return ReEntitiesView(entities: [object])
   }
}

backup

我今天仔细阅读了本指南,最后得到了一个令我满意的解决方案。

https://www.russellgordon.ca/tutorials/core-data-and-xcode-previews/

当您选择包含 CoreData 时,

Xcode 现在使用其项目模板解决了部分问题。已创建 Persistence.swift 文件。如果你往里面看,有一个 static var preview,你可以在其中制作一些提交给“预览上下文”的样本数据。

在您要预览的视图的 PreviewProvider 中,向覆盖 managedObjectContext 的视图实例添加修饰符,改为指向“预览上下文”。

struct ProductsList_Previews: PreviewProvider {
    static var previews: some View {
        ProductsList()
            .environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}

现在,当我的 ProductsList() 视图中的 FetchRequest 运行时,它会使用我在覆盖中使用的“预览上下文”。

在今天找到这篇文章之前,我已经学会了如何做所有这些事情。我 运行 之后遇到的障碍让我看到了这篇文章 - 如何为我的预览提供我的实体的单个示例。如果您也遇到困难,我会推荐这篇文章(在大多数情况下,这似乎是自然而然的下一步)。