-1

I'm trying to setup a picker with dynamic contents and a custom ID, but i'm running into issues getting this working. I'm probably going about this totally wrong.

I'm getting information from a my website using the below code.

function unnamedDecks($pdo) {
$sql = "SELECT u.ID, u.description, c.name
FROM deck_unnamed AS u
LEFT JOIN deck_categories AS c ON c.ID = u.category
WHERE deck IS NULL;";
$q = $pdo->prepare($sql);
$q->execute();
if($q->errorCode() != 0) {
   $errors = $q->errorInfo();
     echo($errors[2]);
}
foreach ($q->fetchAll() as $row) {
  $unnamed[] = array('ID' => $row['ID'], 'name' => $row['name'], 'description' => $row['description']);
}

$arr = array(
             "decks" => (isset($unnamed)) ? $unnamed : "0",
             );

echo json_encode($arr);
}

An example of the response from the function is

{"decks":[{"ID":"69","name":"???","description":"???"},{"ID":"X1","name":"???","description":"???"}]}

Then in the app processing it using

func getUnnamedDecksList() async -> UnnamedDeckList? {
    let downloadTask = Task { () -> UnnamedDeckList in
        let url : String = "****"
        
        var components = URLComponents(string: url)!
        components.queryItems = [
            URLQueryItem(name: "action", value: "unnamedDecks")
        ]
        components.percentEncodedQuery = components.percentEncodedQuery?.replacingOccurrences(of: "+", with: "%2B")
        let (data, _) = try await URLSession.shared.data(from: components.url!)
        let result = String(data: data, encoding: .utf8) ?? ""
        let jsonData = result.data(using: .utf8)!
        let dataRes: UnnamedDeckList = try! JSONDecoder().decode(UnnamedDeckList.self, from: jsonData)
        return dataRes
    }
    let result = await downloadTask.result
    do {
        let categories = try result.get()
        return categories
    } catch {
        print("Unknown error.")
    }
    return nil
}

The setup of the UnnamedDeckList & related class

struct UnnamedDeck : Decodable {
    let name : String
    let ID : String
    let description : String
}

struct UnnamedDeckList : Decodable {
    let decks : [UnnamedDeck]
}

Then trying to display with a picker, where UnnamedDeck.name is what's shown, and ID is it's ID, but this is where I'm getting stuck.

I can get the picker to show what I want by doing the below, but I can't get the ID using it.

let catsArray = getCategoryList()
        Picker("", selection: $category) {
            ForEach(catsArray, id: \.self) {
                Text($0)
            }
        }
1
  • Can you show what is getCategoryList() and how you declare its elements, also show how you declare category. These should be of the same type. In your Picker, you should make the elements of your catsArray Identifiable, then use ForEach(catsArray){ item in ...}. You then have to add Text(item).tag(item) and make sure the tag item is of the same type as your category. Commented Sep 14, 2024 at 22:29

1 Answer 1

0

An alternative to my comment, you could try this approach, declare

@State private var category: String = "" // <--- here, same type as `id`

and use,

 struct UnnamedDeck: Identifiable, Decodable { // <--- here
     let id: String  // <--- here
     let name : String
     let description : String
     
     enum CodingKeys: String, CodingKey {
         case id = "ID"  // <--- here
         case name, description
     }
 }



 let catsArray = getCategoryList()  // assuming array of UnnamedDeck types
 
 Picker("", selection: $category) {
     ForEach(catsArray) {
         Text($0.name)
     }
 }

category has the selected String ID (of property id) for you to use.

Sign up to request clarification or add additional context in comments.

1 Comment

did my answer not work for you?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.