【问题标题】:SwiftUI Previews - unexpected dataSwiftUI 预览 - 意外数据
【发布时间】:2021-04-02 02:40:34
【问题描述】:

我想了解如何在 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)
    }
}

【问题讨论】:

  • 当您执行let testItem = Item.init(context: context) 时,您不会将其传递给ItemView。基本上你是在初始化它,然后把它扔掉。
  • 嗯...但是我可以在预览中看到这个 testItem。我很惊讶我可以看到它与其他物体混合在一起。我应该以某种方式重写我的 ItemView_Previews 结构以仅查看提供的测试值吗?
  • 尝试将testItem.name = "Abc" 替换为testItem.name = "ASDASDASDASD"。然后看看是否出现。
  • 是的,出现了。现在我可以看到“ASDASDASDASD”(来自我的示例数据)和“Test”(来自在实时预览中创建的核心数据对象)的混合。
  • 嗯,好的。忽略我的第一条评论。你能发布Item的初始化代码吗?

标签: swift xcode core-data swiftui preview


【解决方案1】:

为什么我的 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)

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

【讨论】:

  • 哦,这是我在预览中看到 testItem 和其他对象的正常行为吗?是否可以不从上下文中获取先前创建的对象并仅使用 testItem?
  • 查看我的 cmets 到您之前的相关帖子 - 您需要使用不同的内存中堆栈。
  • 或者我之前的问题中的cmets ;)
猜你喜欢
  • 2022-01-25
  • 2020-01-06
  • 1970-01-01
  • 2021-06-28
  • 2020-12-11
  • 2020-04-18
  • 2020-08-13
  • 1970-01-01
相关资源
最近更新 更多