Melhor prática para usar um FetchedResults para preencher um selecionador SwiftUI

Nov 25 2020

Atualmente estou trabalhando com CoreData FetchedResultse SwiftUIs PickerView. Ao fazer isso, encontrei um problema ao usar o FetchedResults para preencher um PickerView:

Obviamente, posso usar o FetchedResults para preencher o PickerView, mas qual solução é a melhor (também da perspectiva da IU / UX) para definir o @State para o Resultado selecionado?

@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)
    }
}

Isso funciona, no entanto, provavelmente não é a maneira mais elegante de criar um novo objeto de usuário vazio para defini-lo como o padrão.

Alguém de vocês tem uma ideia / melhor prática melhor para resolver este problema provavelmente frequente?

Respostas

2 davidev Nov 25 2020 at 17:14

Se você não quiser criar um User () fictício o tempo todo, o que não é uma boa prática como você mencionou, você deve fazer seu FetchRequest em seu init()ou passar seu FetchedResult para outra visualização.

Aqui está uma solução com outra visão

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:

Na verdade, você pode simplesmente declarar sua Pessoa como opcional. Portanto, você não precisa fornecer um padrão. Ao buscar, ele se moverá automaticamente para o primeiro item no seletor. Se desejar selecionar um diferente, você pode usar o método acima. Em relação ao FetchRequest no init () postou uma resposta há alguns meses aqui