0

I have followed this tutorial to learn about dynamic filters and CoreData: https://www.hackingwithswift.com/quick-start/ios-swiftui/dynamically-filtering-fetchrequest-with-swiftui

I have the following code. ContentView.swift:

import SwiftUI

struct ContentView: View {

    @Environment(\.managedObjectContext) var moc
    @State var lastNameFilter = "A"

    var body: some View {

        VStack {
            FilteredList(filter: lastNameFilter)

            Button("Add Examples") {
                let taylor = Singer(context: self.moc)
                taylor.firstName = "Taylor"
                taylor.lastName = "Swift"

                let ed = Singer(context: self.moc)
                ed.firstName = "Ed"
                ed.lastName = "Sheeran"

                let adele = Singer(context: self.moc)
                adele.firstName = "Adele"
                adele.lastName = "Adkins"

                try? self.moc.save()
            }

            Button("Show A") {
                self.lastNameFilter = "A"
            }

            Button("Show S") {
                self.lastNameFilter = "S"
            }
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

FilteredList.swift:

import CoreData
import SwiftUI

struct FilteredList: View {

    var fetchRequest: FetchRequest<Singer>
    var singers: FetchedResults<Singer> { fetchRequest.wrappedValue }

    var body: some View {
        List(singers, id: \.self) { singer in
            Text("\(singer.wrappedFirstName) \(singer.wrappedLastName)")
        }
    }

    init(filter: String) {
        fetchRequest = FetchRequest<Singer>(entity: Singer.entity(), sortDescriptors: [], predicate: NSPredicate(format: "lastName BEGINSWITH %@", filter))
    }

}

//struct FilteredList_Previews: PreviewProvider {
//    static var previews: some View {
//    }
//}

Singer+CoreDataClass.swift:

import Foundation
import CoreData

@objc(Singer)
public class Singer: NSManagedObject {

}

Singer+CoreDataProperties.swift:

import Foundation
import CoreData


extension Singer {

    @nonobjc public class func fetchRequest() -> NSFetchRequest<Singer> {
        return NSFetchRequest<Singer>(entityName: "Singer")
    }

    @NSManaged public var firstName: String?
    @NSManaged public var lastName: String?

    var wrappedFirstName : String {
        firstName ?? "Unknown"
    }

    var wrappedLastName : String {
        lastName ?? "Unknown"
    }

}

Core Data has 1 entity: Singer with 2 String attributes: firstName and lastName. Module: Current Product Module. Codegen: Manual/None.

When I try to preview ContentView, preview crashes. When I open crash logs file and go to Debug Navigator, I can see following error:

Dispatch queue: com.apple.main-thread (0)

On lines:

FilteredList.swift:

var singers: FetchedResults<Singer> { fetchRequest.wrappedValue }

List(singers, id: \.self) { singer in

AppDelegate.swift:

class AppDelegate: UIResponder, UIApplicationDelegate {

What can be the problem? wrappedValue? What is wrong with the code?

EDIT: Here is a link to crash log file on my Dropbox: crash-logs

2
  • Can you provide somehow full crashlog? Commented Dec 24, 2019 at 5:31
  • Hi, Asperi. I have just edited my question and added link to crash logs file at the end. Commented Dec 26, 2019 at 0:24

2 Answers 2

2

What helped me was changing struct ContentView_Previews(...) to:

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

I have also changed struct FilteredList_Previews(...) to:

struct FilteredList_Previews: PreviewProvider {
    static var previews: some View {
        let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
        return FilteredList(filter: "A").environment(\.managedObjectContext, context)
    }
}

Kudos to @Gergely as he helped me with similar problem here: https://stackoverflow.com/a/59629730/12315994

Sign up to request clarification or add additional context in comments.

Comments

0

I had the same scenario. Providing the context from the AppDelegate to the preview and adding data to that fixed the crash for me:

struct FilteredList_Previews: PreviewProvider {
  static var previews: some View {
    let moc = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
    let taylor = Singer(context: moc)
    taylor.firstName = "Taylor"
    taylor.lastName = "Swift"
    return FilteredList().environment(\.managedObjectContext, moc)
  }
}

Unfortunately, the data does not show the exact data I would expect (it shows duplicated entries). But for me it's good enough to preview the design of the view. Hope that still helps.

2 Comments

Thanks, but on line let taylor = Singer(context: self.moc) I was getting an error Type 'FilteredList_Previews' has no member 'moc' I have solved this another way thanks to help from @Gergely. Please check my answer to this question. Maybe you will find it useful as well.
Except that I forgot to strip self. from the context parameter that's exactly my suggestion. I'll still update my response if someone else finds it helpful.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.