I have a parent view which does a @FetchRequest
and passes the FetchedResults<T>
to a child view. Everything works, and the child view is able to parse through the FetchedResults
. However, I can't figure out how to set up the data so that the child's Preview
struct will work. What's the proper way to set up some constant data in Preview
struct so that I can instantiate the child view and pass in FetchedResults<T>
?
Asked
Active
Viewed 4,546 times
12

andrw
- 790
- 1
- 8
- 20
-
I realize I can do the fetch request within the child view itself, and most examples I find online are doing that. However, I want to avoid doing that extra query. – andrw Apr 29 '20 at 05:54
2 Answers
13
As FetchedResults<T>
is a RandomAccessCollection
and swift array also is a RandomAccessCollection
, here is possible solution.
Update: verified with Xcode 13.3 / iOS 15.4
struct ContentView: View {
@Environment(\.managedObjectContext) var context
@FetchRequest(entity: Person.entity(), sortDescriptors: [])
var result: FetchedResults<Person>
var body: some View {
VStack(alignment: .leading) {
Text("Persons").font(.title)
PersonsView(results: result) // FetchedResults<Person> is a collection
}
}
}
// generalize PersonsView to depend just on collection
struct PersonsView<Results:RandomAccessCollection>: View where Results.Element == Person {
let results: Results
var body: some View {
ForEach(results, id: \.self) { person in
Text("Name: \(person.name ?? "<unknown>")")
}
}
}
// Tested with Xcode 11.4 / iOS 13.4
// DOES NOT WORK ANYMORE !!
// struct ChildView_Previews: PreviewProvider {
// static var previews: some View {
// PersonsView(results: [Person()]) // << use regular array //to test
// }
}
Update: fixed & tested part for Xcode 12 / iSO 14 (due to crash of above PreviewProvider)
It appears entity now should be read & specified explicitly:
struct ChildView_Previews: PreviewProvider {
static let entity = NSManagedObjectModel.mergedModel(from: nil)?.entitiesByName["Person"]
static var previews: some View {
let person = Person(entity: entity!, insertInto: nil)
person.name = "Test Name"
return PersonsView(results: [person])
}
}

Martijn Pieters
- 1,048,767
- 296
- 4,058
- 3,343

Asperi
- 228,894
- 20
- 464
- 690
-
I have tried this in both Xcode 11.6 and the 12.0 beta and the preview panel crashes every time. I'd love to have this working, any idea what might be happening in more recent builds of Xcode? – stanlemon Aug 13 '20 at 01:49
-
@Asperi thanks, it's working fine for a FetchedResults. I'm trying to do the same for a SectionedFetchResult but I don't understand how to deal with this. Can you help please? – alpennec Apr 19 '23 at 20:06
8
Use the preview PersistenceController within your pre-generated PersistenceController struct (inside the "Persistence.swift" file).
so if you pass an item from a Core Data "Item"-entity:
struct ContentView: View {
...
private var items: FetchedResults<Item>
..
ForEach(items) { item in
DetailView(item: item)
}
..
In the Detail-View go like this:
struct DetailView: View {
var item: FetchedResults<Item>.Element
var body: some View {
Text("Items text = \(item.text ?? "")")
}
}
struct Detail_Previews: PreviewProvider {
static var previews: some View {
let viewContext = PersistenceController.preview.container.viewContext
let previewItem = Item(context: viewContext)
previewItem.text = "Text4preview"
return Detail(item: previewItem)
}
}

user14534957
- 336
- 3
- 10