Getting picker selected value with api data

Hi,
I'm getting data from an api and reading it to a model that contains (among other things) an id and a name.

I can get the picker to populate using a ForEach loop so that when I click, I get the list showing the name, I just can't seem to return the id and then show the name in the picker as the selected item.

I feel like I'm missing something simple, but just can't seem to spot it.

Code Block
Picker("Pick an item", selection: $ID) {
ForEach(mydata, id: \.ID) { mymodel in
Text(mymodel.Name)
}
}.onAppear(perform: loadData)
Text("Selected: \(ID)")

Any help would be gratefully received.
Thanks
Answered by OOPer in 670274022

This is my complete code:

Far from complete. Simply saying a complete code is a self contained code which can be built and run without any guesses.

Sorry, didn't think that you'd need that as well

If you could guess what is needed for readers properly, more readers would take time to solve your issue and you would get better responses sooner.


You declare ID of MyModel as String, so the type of selection needs to match to it:
Code Block
struct MyView: View {
@State var mydata = [MyModel]()
@State private var ID: String = "" //<-
var body: some View {
NavigationView {
Form {
Section {
Picker("Pick an item", selection: $ID) {
ForEach(mydata, id: \.ID) { mymodel in
Text(mymodel.Name) //`name` or `Name`
}
}.onAppear(perform: loadData)
Text("Selected: \(ID)")
}
}
}
}
//...
}


Assuming your loadData() works properly. But generally, you should better not dispose error info silently:
Code Block
func loadData() {
guard let url = URL(string: "https://mysite.co.uk/api/getmydatalist") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print(error)
return
}
guard let data = data else {
print("data is nil")
return
}
do {
let response = try JSONDecoder().decode([MyModel].self, from: data)
DispatchQueue.main.async {
self.mydata = response
}
} catch {
print(error)
}
}.resume()
}


What do you get in Text line 7 ?

How did you define ID ?

Please show the complete code.
Here is a small example that hope may help:
Code Block
struct ContentView: View {
var activities = ["Run", "Walk", "Swim"]
@State private var selectedActivity = 0
var body: some View {
Picker(selection: $selectedActivity, label: Text("Activity").frame(width: 200,alignment: .center)) {
ForEach(0 ..< activities.count) {
Text(self.activities[$0])
}
.pickerStyle(WheelPickerStyle())
}
Text("You selected: \(self.activities[selectedActivity])")
}
}

Hi,
Thanks for the reply.
I can get it working using your above example (I based my code off a very similar example), my problem is getting the ID that's used in the model.

This is my complete code:

Code Block
@State var mydata = [MyModel]()
@State private var ID = 0
var body: some View {
NavigationView {
Form {
Section {
Picker("Pick an item", selection: $ID) {
ForEach(mydata, id: \.ID) { mymodel in
Text(mymodel.name)
}
}.onAppear(perform: loadData)
Text("Selected: \(ID)")
}
}
}
}
func loadData() {
guard let url = URL(string: "https://mysite.co.uk/api/getmydatalist") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
if let response = try? JSONDecoder().decode([MyModel].self, from: data) {
DispatchQueue.main.async {
mydata = response
}
return
}
}
}.resume()
}

I use the same function elsewhere to populate my model collection which I use in a list, its just the picker that's giving me issues.

Thanks
You do not show how Model is defined…
The model is a simple struct

Code Block
import Foundation
let myData = [MyModel]()
struct MyModel: Hashable, Codable {
var ID: String
var Name: String
var www: String?
var Facebook: String?
var Twitter: String?
var Instagram: String?
var Email: String?
var Phone: String?
var Location: String?
var Address1: String?
var Address2: String?
var Town: String?
var County: String?
var Postcode: String?
var What3Words: String?
}

Sorry, didn't think that you'd need that as well

the picker needs to show the name and the selected value needs to be the ID.

thanks
Accepted Answer

This is my complete code:

Far from complete. Simply saying a complete code is a self contained code which can be built and run without any guesses.

Sorry, didn't think that you'd need that as well

If you could guess what is needed for readers properly, more readers would take time to solve your issue and you would get better responses sooner.


You declare ID of MyModel as String, so the type of selection needs to match to it:
Code Block
struct MyView: View {
@State var mydata = [MyModel]()
@State private var ID: String = "" //<-
var body: some View {
NavigationView {
Form {
Section {
Picker("Pick an item", selection: $ID) {
ForEach(mydata, id: \.ID) { mymodel in
Text(mymodel.Name) //`name` or `Name`
}
}.onAppear(perform: loadData)
Text("Selected: \(ID)")
}
}
}
}
//...
}


Assuming your loadData() works properly. But generally, you should better not dispose error info silently:
Code Block
func loadData() {
guard let url = URL(string: "https://mysite.co.uk/api/getmydatalist") else {
print("Invalid URL")
return
}
let request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
print(error)
return
}
guard let data = data else {
print("data is nil")
return
}
do {
let response = try JSONDecoder().decode([MyModel].self, from: data)
DispatchQueue.main.async {
self.mydata = response
}
} catch {
print(error)
}
}.resume()
}


Thanks. All it was the selection needed to be set to a string.
Should have spotted that.
Really appreciate the help.
Getting picker selected value with api data
 
 
Q