SwiftUI 预览 - 意外数据

问题描述

我想了解如何在 SwiftUI Canvas Preview 中处理示例数据。我已经做了一些搜索,但没有找到我的问题的答案。

问题:

为什么我的 ItemView.swift 视图的预览显示了我提供的示例数据 + 在实时预览中创建的核心数据模型的混合?

预览代码示例

struct ItemView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        //Test data
        let testItem = Item.init(context: context)
        testItem.name = "Abc"
        return ItemView(filter: false)
            .environment(\.managedobjectContext,context)
    }
}

预期行为: 我期待看到带有测试数据的 UI 预览。换句话说,我期待在预览中看到“Abc”。

实际行为 但我看到的是一个混合项目列表:“Abc”重复了几次。 “测试”重复了几次(因为它是在实时预览中使用加号按钮创建的 Core Data 对象的 item.name 属性)。

这是为什么?当我专门提供了测试值 (testItem.name = "Abc") 时,为什么我会看到 Core Data 对象?

--

完整的工作示例

ContentView.swift

import SwiftUI
import CoreData

struct ContentView: View {
    
    @Environment(\.managedobjectContext) var managedobjectContext
    @State var paidFilter :Bool? = nil
    
    
    var body: some View {
        
        NavigationView {
            List {
                
                ItemView(filter: paidFilter)
                
            }
            .listStyle(PlainListStyle())
            .navigationTitle(Text("Items"))
            .navigationBarItems(
                trailing:
                    
                    Button(action: {
                        let item = Item(context: self.managedobjectContext)
                        item.name = "Test"
                        
                        do {
                            try self.managedobjectContext.save()
                        }catch{
                            print(error)
                        }
                        
                    }) {
                        Image(systemName: "plus.circle.fill")
                            .font(.title)
                    }
            )
        }
        .navigationViewStyle(StackNavigationViewStyle())
        
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return ContentView()
            .environment(\.managedobjectContext,context)
    }
}

ItemView.swift

import SwiftUI

struct ItemView: View {
    @Environment(\.managedobjectContext) var managedobjectContext
    var fetchRequest: FetchRequest<Item>
    var items: FetchedResults<Item> { fetchRequest.wrappedValue }
    
    init(filter: Bool?) {
        fetchRequest = FetchRequest<Item>(entity: Item.entity(),sortDescriptors: [])
    }
    
    var body: some View {
        vstack {
            ForEach(items,id: \.self) {item in
                Text("\(item.name ?? "test123")")
            }
        }
    }
}

struct ItemView_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        //Test data
        let testItem = Item.init(context: context)
        testItem.name = "Abc"
        return ItemView(filter: false)
            .environment(\.managedobjectContext,context)
    }
}

解决方法

为什么我的 ItemView.swift 视图的预览显示了我提供的示例数据 + 在实时预览中创建的核心数据模型?

  1. 以下行启动持久数据的上下文,因此可以获取所有存储的核心数据对象

     let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
  2. 下面这行在上面创建的上下文中创建了一个新对象,因此它在上下文中(尽管已存储)并可与其他存储的对象一起获取。

     let testItem = Item.init(context: context)
    

因此从这个上下文中获取对象......

    return ItemView(filter: false)
        .environment(\.managedObjectContext,context)

... 使所有 - 存储和创建 - 在预览中可用。