Home > database >  Pick element of an array based on Picker selection
Pick element of an array based on Picker selection

Time:11-03

It's easier to ask the question if I give you a simplified example of what I would like to achieve, so please bear with me!

I have a struct - let‘s say, users, something simple.

struct User: Identifiable {
    var id = UUID()
    var userName: String
    var userRegistrationDate: String
}

//example of a User instance:
User(userName: "Graham Bell", userRegistrationDate: "12.12.2022")

I create 3 different instances of User and place them into a list. The list can continuously be expanded with new instances of User.

let userList: [User] = [User1, User2, User3]

//User1, User2, User3 are instances of User.

I would like to create a Picker.

The Picker should loop through User.userName, and when I click on a UserName from the dropdown menu, I would like the App to load the User that has the specific username I chose from the picker, with its properties and methods.

To be more precise:

struct aListView: View {

@State var selectedUserName: String = ""
@State var selectedUser: User = User(...)
@State var userList: [User] = [User1, User2, User3]

var body: some View {

List {

Picker("User Name:", selection: $selectedUserName) {
                    ForEach(userList) { user in
                        Text(user.userName)
                    }
                }

 HStack {
         Text("Registration Date:")
         Spacer()
         Text(selectedUser.registrationDate)
        }
}

The problem:

I select a userName from the dropdown menu. the userName is one of the two properties of each User instance - basically I choose the User by their name.

After I selected the name of the User I want to load, I need to somehow retrieve the registrationDate property for the User whose name I picked.

I thought of creating a @State selectedUser variable, which changes depending on the @State selectedUserName variable, tied to the Picker.

I somehow need to create a connection between these @State variables, a function of some sorts that loops through the list of Users, finds the user with the name selected in the picker, changes the @State var selectedUser to that User with the name I picked. Only after that, I can retrieve that user‘s registration date.

How should I proceed? Bear in mind this is a very simplified example of what I am working with. I am trying to create a complex data structure, with a lot of properties and methods. So I don‘t think I can find an if/else solution to this.

Please help :(

CodePudding user response:

Try this approach, where selectedUser in the Picker is of User type, (note you can make it an Optional type, if desired).

With this approach, you have direct access to all the properties of the selected user, as shown in the example code.

struct ContentView: View {
    var body: some View {
        MyListView()
    }
}

struct User: Identifiable, Hashable {   // <-- here
    var id = UUID()
    var userName: String
    var userRegistrationDate: String
}

struct MyListView: View {
    @State var selectedUser = User(userName: "", userRegistrationDate: "") // <-- here
    // for testing
    @State var userList = [User(userName: "Graham Bell", userRegistrationDate: "12.12.2022"),
                           User(userName: "xxxx", userRegistrationDate: "10.10.2010"),
                           User(userName: "yyyy", userRegistrationDate: "9.9.2009")]
    
    var body: some View {
        List {
            Picker("User Name:", selection: $selectedUser) {
                ForEach(userList) { user in
                    Text(user.userName).tag(user) // <-- here
                }
            }
            HStack {
                Text("Registration Date:")
                Spacer()
                Text(selectedUser.userRegistrationDate)  // <-- here
            }
        }
        .onAppear {
            // setting the initial selection
            if let usr = userList.first {
                selectedUser = usr
            }
        }
    }
}
  • Related