mallow
mallow

Reputation: 2856

SwiftUI Previews - unexpected data

I would like to understand how to work with example data in SwiftUI Canvas Preview. I have done some searching, but didn't find answer to my problem.

Question:

Why Preview of my ItemView.swift view shows a mixture of example data I have provided + Core Data models created in Live Preview?

Preview code example

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)
    }
}

Expected behaviour: I was expecting to see UI preview with test data. So in other words, I was expecting to see "Abc" in Preview.

Actual behaviour But what I am seeing is a list of mixed items: "Abc" repeated few times. "Test" repeated few times (as it's item.name attribute of Core Data objects being created with plus button in Live Preview).

Why is that? Why am I seeing Core Data objects, when I have specifically provided test values (testItem.name = "Abc")?

--

FULL WORKING EXAMPLE

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)
    }
}

Upvotes: 2

Views: 213

Answers (1)

Asperi
Asperi

Reputation: 257693

Why Preview of my ItemView.swift view shows a mixture of example data I have provided + Core Data models created in Live Preview?

  1. the below line initiates context to your persistent data, so makes available all stored core data object to be fetched

     let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    
  2. the below line creates a new object in the context created above, so it is in context (though to stored) and available for fetching alongside of others stored.

     let testItem = Item.init(context: context)
    

Thus fetching object from this context ...

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

... makes all - stored and created - available in Preview.

Upvotes: 1

Related Questions