SwiftUI: How to pass core data objects to views?

Viewed 2007

What I want to do: pass a reference to a NSManagedObject of a FetchRequest (here from: TestView) to another Child-View (here: LogRectangle).

What I tried: These are basically the important lines:

List(testObjects, id: \.self) { habit in
    LogRectangle(testObject: testObject)
}

And this is the whole code:

struct TestView : View {
    @Environment(\.managedObjectContext) var managedObjectContext
    @FetchRequest(
        entity: TestObject.entity(),
        sortDescriptors: [NSSortDescriptor(keyPath: \TestObject.name, ascending: true)]
    ) var testObjects: FetchedResults<TestObject>


    var body: some View {
        NavigationView {
            HStack {
                Button(action: {
                    let testObject = TestObject(context: self.managedObjectContext)
                    habit.name = "TestObject String"
                    do {
                        try self.managedObjectContext.save()
                    } catch {
                        // handle the Core Data error
                    }
                }) {
                    Text("Insert example TestObject")
                }
                List(testObjects, id: \.self) { habit in
                    LogRectangle(testObject: testObject)
                }
            }
                .navigationBarTitle("Test")
        }
    }
}

struct LogRectangle : View {
    var habit : TestObject

    var body: some View {
        Text(habit.name)
            .font(.title)
            .foregroundColor(.white)        
    }
}

Here I get this error on the line with the text in the class LogRectangle.

Cannot convert value of type 'String?' to expected argument type 'LocalizedStringKey'
2 Answers

You are encountering this error perhaps because the attribute, name, is defined as an optional string in the data model.

The Text struct does not take an optional value. It has to be an explicit value that is:

  • A value conforming to the StringProtocol
  • A literal string that can be used for loading a localized string

Parameters for Text struct

Therefore, you will need to make some changes to the model that you are passing to the LogRectangle. These change can either be made at the data model level (and then updating the associated NSManagedObject class, or you can have a computed property on the model to provide a non-optional value of the attribute.

You may have better luck using the testObject indices for the list rather than iterating on the actual objects. Try this:

List(testObjects.indices, id: \.self) { index in
     LogRectangle(testObject: testObjects[index])
}
Related