0

This particular SwiftUI List, made up of array, I can not seem to select it. Even though I tried with Set(). or @Binding. everything online resource has to offer. Wrong type? or something might have to be about Identifiable? View? Array? I'm totally new here. Related document would be appreciated.

And also how can I access/take the data of selected item and append it into another Array let's say a cart (for e-commerce app for example)

Thank you in advance

import SwiftUI

struct CategoryT1: View {
    //
    @State private var a1: String?
    @State private var a2: SingleItem?
    // @Binding private var a3: SingleItem?   // Doesn't work & cause other error
    // @State private var a3 = Set<SingleItem>() // No Error, but still can't select
    @State private var a3: SingleItem? // This couldn't get select
    //***** Array 1
    let users = ["John", "Jane", "Jim", "Jill"]
    //***** Array 2
    var arrayOfSingleItem = [
        SingleItem(name: "car",
                   idd: "NYC-0202",
                   size: "SUV",
                   price3: "5",
                   price: "6"),
        SingleItem(name: "tank",
                   idd: "NYC-2",
                   size: "Big",
                   price3: "7",
                   price: "9")
    ]
    //***** Array 3
    var dataOfItem =
    [
        ["Candy","0123456","small","95","95"  ],
        ["Cake","005500","10 pound","108","108" ],
    ]
    //*****
    var body: some View {
        Text("Category")
        //**** 1
        List(users, id:\.self, selection: $a1) { user in
            Text(user)
        }
        //**** 2
        List(arrayOfSingleItem, id:\.self, selection: $a2) { x in
            CellRowView(product: x)
        }
        //**** 3   // This couldn't get select
        List(dataOfItem, id:\.self, selection: $a3) { x in
            CellRowView(product: SingleItem(
                name: x[0],
                idd: x[1],
                size: x[2],
                price3: x[3],
                price: x[4])
            )
        }
        
    }
}

#Preview {
    CategoryT1()
}

SingleItem.swiftui would look like this

import SwiftUI

struct SingleItem: Identifiable, Hashable {
     let id = UUID()
     var name: String
     var idd:  String
     var size: String
     var price3: String
     var price: String
 }
//
struct CellRowView: View {
    var product: SingleItem

    var body: some View {
        VStack(alignment: .leading, spacing: 3) {
            Text(product.name)
                .foregroundColor(.primary)
                .font(.headline)
            HStack(spacing: 3) {
                Text(product.idd)
            }
            .foregroundColor(.secondary)
            .font(.subheadline)
        }
    }
}

1 Answer 1

1

Try this approach where you use a .tag(a2) to identify your a2 selection, same for a3.

Note, your dataOfItem is an array of array of Strings, re-make it into a array of strutc to make it easier to work with.

Note, you should also not use x[..] in your real code. Similarly, do not use id:\.self in the lists, ensure the items are unique Identifiable.

To ... access/take the data of selected item and append it into another Array just use the selections variables a1, a2 or a3, and to trigger some function when they change, use .onChange(of: ...)

For more info, read the basics of SwiftUI again, especially @State and List.

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

struct CategoryT1: View {
    @State private var a1: String?
    @State private var a2: SingleItem?
    @State private var a3: SingleItem?
    
    //***** Array 1
    let users = ["John", "Jane", "Jim", "Jill"]
    
    //***** Array 2
    var arrayOfSingleItem = [
        SingleItem(name: "car",
                   idd: "NYC-0202",
                   size: "SUV",
                   price3: "5",
                   price: "6"),
        SingleItem(name: "tank",
                   idd: "NYC-2",
                   size: "Big",
                   price3: "7",
                   price: "9")
    ]
    
    //***** Array 3
    var dataOfItem =
    [
        ["Candy","0123456","small","95","95"  ],
        ["Cake","005500","10 pound","108","108" ]
    ]

    var body: some View {
        Text("Category")
        //**** 1
        List(users, id:\.self, selection: $a1) { user in
            Text(user)
        }
        //**** 2
        List(arrayOfSingleItem, selection: $a2) { x in
            CellRowView(product: x)
                .tag(x) // <--- here
        }
        //**** 3
        List(dataOfItemAsArrayOfSingleItem(), selection: $a3) { item in
            CellRowView(product: item)
                .tag(item) // <--- here
        }
        
        // for testing to display the selections
        Text("selected a1 user: \(a1 ?? "no user")")
        Text("selected a2 SingleItem: \(a2?.name ?? "nothing")")
        Text("selected a3 SingleItem: \(a3?.name ?? "nothing")")

            .onChange(of: a1) {
                print("---> a1 value changed: \(a1 ?? "no user")")
            }
    }
    
    // --- here
    func dataOfItemAsArrayOfSingleItem() -> [SingleItem] {
         dataOfItem.map {
            SingleItem(name: $0[0], idd: $0[1], size: $0[2], price3: $0[3], price: $0[4])
        }
    }
}

Ok, for the row highlight, try this alternative example of the code, where dataOfItemAsArrayOfSingleItem is an array of [SingleItem], not a function, as in the previous example code.

struct CategoryT1: View {
    @State private var a1: String?
    @State private var a2: SingleItem?
    @State private var a3: SingleItem?
    
    @State private var dataOfItemAsArrayOfSingleItem: [SingleItem] = [] // <--- here
    
    //***** Array 1
    let users = ["John", "Jane", "Jim", "Jill"]
    
    //***** Array 2
    var arrayOfSingleItem = [
        SingleItem(name: "car", idd: "NYC-0202", size: "SUV", price3: "5", price: "6"),
        SingleItem(name: "tank", idd: "NYC-2", size: "Big", price3: "7", price: "9")
    ]
    
    //***** Array 3
    var dataOfItem =
    [
        ["Candy","0123456","small","95","95"  ],
        ["Cake","005500","10 pound","108","108" ]
    ]

    var body: some View {
        Text("Category")
        //**** 1
        List(users, id:\.self, selection: $a1) { user in
            Text(user)
        }
        //**** 2
        List(arrayOfSingleItem, selection: $a2) { x in
            CellRowView(product: x)
                .tag(x) // <--- here
        }
        //**** 3
        List(dataOfItemAsArrayOfSingleItem, selection: $a3) { item in
            CellRowView(product: item)
                .tag(item) // <--- here
        }
        
        // for testing to display the selections
        Text("selected a1 user: \(a1 ?? "no user")")
        Text("selected a2 SingleItem: \(a2?.name ?? "nothing")")
        Text("selected a3 SingleItem: \(a3?.name ?? "nothing")")

            .onChange(of: a1) {
                print("---> a1 value changed: \(a1 ?? "no user")")
            }
        
            // <--- here, populate the array on start
            .onAppear {
                dataOfItemAsArrayOfSingleItem = dataOfItem.map {
                    SingleItem(name: $0[0], idd: $0[1], size: $0[2], price3: $0[3], price: $0[4])
                }
            }
    }

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

2 Comments

It works. The selection also work as the print confirm. However, in the UI it doesn't seems to function properly as there's no highlight. Is there anyway to fix this? I tried .listRowBackground. .onGesture. nothing works so far. Thank you
updated my answer for the highlight of the selection a3

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.