如何使用 foreach 在 SwiftUI 中基于测试数据创建单元格的多个预览

How to create multiple previews of cells based on test data in SwiftUI with a foreach

我正在尝试显示卡片视图的多个预览(Apple 的 SwiftUI 教程)。我设法使用 Group 结构手动完成。

struct CardView_Previews: PreviewProvider {
    
    static var previews: some View {
        Group {
            CardView(scrum: DailyScrum.data[0])
                .background(DailyScrum.data[0].color)
            CardView(scrum: DailyScrum.data[1])
                .background(DailyScrum.data[1].color)
        }.previewLayout(.fixed(width: 400, height: 60))
    }
}

我想使用 ForEach 自动显示基于测试数据的四个单元格,但无法生成以下内容,编译器无法为表达式生成诊断。

struct CardView_Previews: PreviewProvider {
    
    static var previews: some View {
        Group {
            ForEach(DailyScrum.data) { scrum in
                CardView(scrum: scrum)
                    .background(scrum.color)
            }
        }.previewLayout(.fixed(width: 400, height: 60))   
    }   
}

有没有一种方法可以在不显式创建每个预览的情况下构建预览?

您无法将 PreviewProvider 视为 运行 应用程序的一部分。它仅在您为该特定视图使用 canvas 上的预览时使用。因此,您需要提供给视图的任何数据都必须来自或通过 PreviewProvider 本身提供。

从您的代码看来,您的模型 DailyScrum 包含一个用于填充单元格的数组 data。因此,如果您想在 PreviewProvider 中声明它,您可以这样声明它:

struct CardView_Previews: PreviewProvider {
    
    let dailyScrum = DailyScrum(
        // Initialize your data here
    )

    static var previews: some View {
        Group {
            ForEach(dailyScrum.data) { scrum in
                CardView(scrum: scrum)
                    .background(scrum.color)
            }
        }.previewLayout(.fixed(width: 400, height: 60))   
    }   
}

如果这是您可能在其他视图中使用的模型数据,那么您可能希望遵循 DRY 而不是通过在所有 PreviewProviders 中声明相同的数据来重复自己。在那种情况下,我会像这样在模型本身中对您的数据进行 static let

...
static let previewData = DailyScrum(
        // Initialize your data here
    )
...

然后像这样在您的 PreviewProvider 中使用它:

struct CardView_Previews: PreviewProvider {

    static var previews: some View {
        Group {
            ForEach(DailyScrum.previewData) { scrum in
                CardView(scrum: scrum)
                    .background(scrum.color)
            }
        }.previewLayout(.fixed(width: 400, height: 60))   
    }   
}

这种写法假设DailScrum符合Identifiable。如果没有,它应该,否则你将不得不把你的 ForEach 写成 ForEach(DailyScrum.previewData, id: \.self) 或模型的其他部分,你可以用它来识别各个元素。

我通过简单地将 id 参数添加到 ForEach 初始值设定项来找到了我正在寻找的解决方法。它避免了必须添加 Identifiable 符合类型 :

struct CardView_Previews: PreviewProvider {
    
    static var previews: some View {
        Group {
            ForEach(DailyScrum.data, id: \.title) { scrum in
                CardView(scrum: scrum)
                    .background(scrum.color)
            }
        }.previewLayout(.fixed(width: 400, height: 60))
        
    }
    
}