使用 FetchedResults 填充 SwiftUI Picker 的最佳实践

Best Practice for using a FetchedResults for populating a SwiftUI Picker

我目前正在与 CoreData FetchedResultsSwiftUIs PickerView 合作。这样做时,我在使用 FetchedResults 填充 PickerView 时遇到了问题:

我显然可以使用 FetchedResults 来填充 PickerView,但是哪种解决方案最好(也是从 UI/UX 的角度来看)为所选结果定义 @State?

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

这确实有效,但它可能不是最优雅的方式来创建一个新的空用户对象以将其设置为默认值。

你们有没有更好的想法/最佳实践来解决这个可能经常出现的问题?

如果您不想一直创建一个虚拟 User(),这不是您提到的好的做法,您必须在 init() 中执行 FetchRequest 或将 FetchedResult 传递给另一种观点。

这是另一种观点的解决方案

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

    }
}

编辑:

实际上你可以将你的 Person 声明为可选的。因此您不必提供默认值。获取时,它将自动移动到选择器中的第一个项目。如果您希望 select 有所不同,您可以使用上面的方法。关于 init() 中的 FetchRequest,它在几个月前发布了一个答案