0
votes

I am relatively new to SwiftUI and would like to have a view where the user selects a result from a CoreData FetchRequest in a Picker. I have the following lines inside the view struct but outside the view body,

@FetchRequest(
    entity: Person.entity(),
        sortDescriptors: [
            NSSortDescriptor(keyPath: \Person.name, ascending: true)
        ]
) var people: FetchedResults<Person>
    
@State var currentPerson:Person

Inside the view body, I have got a Picker that saves the selected value to currentPerson but when I try to run the program in the simulator, I get an error that states Missing argument for parameter 'currentPerson' in call at the preview struct at the end of the file.

If I try to initialise currentPerson with the first item in people I get a error that states Cannot use instance member 'people' within property initializer; property initializers run before 'self' is available.

Apart from passing a Person object into the view, the other solution that I have had work is the create an object to initialise currentPerson variable is to create a Person object but not pass the Managed Object Context as the parameter.

However when I run the program it shows CoreData: error: Failed to call designated initializer on NSManagedObject class 'Person' in the console, but the program runs as intended.

Is this the best way to do this or am I missing something that would work better? Thanks!

1
The problem is that you are trying to (1) run the fetch request and (2) set up the currentPerson variable at the same time. When in reality, you need the fetch request to complete before you can access the returned data. One solution might be to make currentPerson optional and initialize it without a value (@State var currentPerson:Person = nil). - nicksarno
@nicksarno it'd need a question mark, too -- @State var currentPerson : Person? = nil - jnpdx
@nicksarno @jnpdx Thanks for the help, this has done exactly what I was looking for! I also had to add as Person? to the Picker tag and some checks for if the currentPerson variable was still nil. - brownandrew15

1 Answers

0
votes

Use a computable property. That will not be called until after self is available. Then, as was said above, use an optional calculated property for the first person.

var people : [Person] {
    let fetchRequest = Person.fetchRequest()
    fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \Person.name, ascending: true)]

    return fetchRequest.wrappedValue
}

var currentPerson : Person? {
    return people.first
}