Mejores prácticas para usar FetchedResults para completar un SwiftUI Picker

Nov 25 2020

Actualmente estoy trabajando con CoreData FetchedResultsy SwiftUIs PickerView. Mientras lo hacía, encontré un problema al usar FetchedResults para completar un PickerView:

Obviamente, puedo usar FetchedResults para completar PickerView, pero ¿qué solución es la mejor (también desde la perspectiva UI / UX) para definir el @State para el resultado seleccionado?

@FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.lastName, ascending: true)], animation: .default) private var users: FetchedResults<User>
@State var user: User = User()

// ...

Picker(selection: $user, label: Text("User")) {
    ForEach(users) { user in
        Text(lastName).tag(user)
    }
}

Esto funciona, sin embargo, probablemente no sea la forma más elegante de crear un nuevo objeto de usuario vacío para establecerlo como predeterminado.

¿Alguno de ustedes tiene una mejor idea / mejor práctica para resolver este problema que probablemente a menudo?

Respuestas

2 davidev Nov 25 2020 at 17:14

Si no desea crear un User () ficticio todo el tiempo, lo cual no es una buena práctica como mencionó, debe hacer su FetchRequest en su init()o pasar su FetchedResult a otra vista.

Aquí hay una solución con otra vista.

struct ContentView : View {
    
    @FetchRequest(sortDescriptors: [NSSortDescriptor(keyPath: \User.lastName, ascending: true)], animation: .default) private var users: FetchedResults<User>

    var body : some View {
        PickerView(users: Array(users))
    }
}

struct PickerView : View {

    var users : [User]
    @State var selectedUser : User?
    
    init(users: [User]) {
        self.users = users
        self._selectedUser = State(initialValue: users.first)
    }
    
    var body : some View {
        Picker(selection: $selectedUser, label: Text("Users")) {
            ForEach(users) { user in
                Text(user.lastName ?? "").tag(user as User?)
            }
        }

    }
}

Editar:

En realidad, puede declarar su Persona como opcional. Por lo tanto, no es necesario que proporcione un archivo predeterminado. Al buscarlo, se moverá automáticamente al primer elemento del selector. Si desea seleccionar un método diferente, puede utilizar el método anterior. Con respecto a FetchRequest en init (), publicó una respuesta hace un par de meses aquí