I am trying to update a state variable that is an array of Strings that I get back from an API call. I want to display this array in a Picker. However, my Picker is completely blank. I know my api is coming back with values because one of the ForEach's is updating.
struct SelectModeView: View {
@StateObject var viewModel = SelectModeViewModel()
@State private var selectionB: String = ""
var body: some View {
ZStack {
Color.white
.edgesIgnoringSafeArea(.all)
VStack {
VStack(spacing: 08) {
Text("PICKER STYLE")
.font(.largeTitle)
Text("Select Project")
Picker("Select Project", selection: self.$selectionB) {
ForEach(self.projects, id: \.self) { option in
Text(option)
}
}
.accentColor(Color.black)
}
Text("DISCLOSURE GROUP STYLE")
.font(.largeTitle)
DisclosureGroup(self.selectionC == "" ? "Pick Project" : self.selectionB, isExpanded: self.$isProjectOpen, content: {
ScrollView(.vertical, showsIndicators: false) {
VStack {
ForEach(self.projects, id: \.self) { option in
Text(option)
.padding()
}
}
}
.frame(height: 240)
})
.accentColor(Color.black)
.padding(.horizontal, 64)
}
}
.onAppear {
print("selectModeView appeared")
self.viewModel.gatherProjectListAPI()
}
.onReceive(self.viewModel.$projectList, perform: { list in
print("Received project list: \(list)")
self.projects = list
})
}
}
class SelectModeViewModel: ObservableObject {
@Published var projectList: [String] = []
func gatherProjectListAPI() {
self.projectList.append("Project1")
self.projectList.append("Project2")
self.projectList.append("Project3")
self.projectList.append("Project4")
// same result as self.projectList = ["Project1", "Project2", "Project3", "Project4"]
}
}
I have tried not using an id, going by only count of the array (0..<projects.count), not using " option in" and using $0 instead, using only the published variable in the viewModel (which would be preferred to do) and not only having the published variable being received and updating a state variable and have still not been able to get the Picker to update.
viewModel.projectListin theForEach, instead of your nonsensicalself.projects. Note, there is no need for your.onReceive(...), theprojectListis already being observed by the view. Note also, usingForEach(viewModel.projectList, id: \.self)may work but it is not appropriate, you should make sure the elements are unique by having a uniqueid. Use theidfor the selection and forText(option).tag(id). With the current code, you should addselectionB = viewModel.projectList.first ?? ""to your.onAppear.