阅读 Json 并添加到选择器 swiftUI

Read Json and Add to picker swiftUI

  struct Test: View {
    
    @ObservedObject var datas2 = ReadData2()
    @State var selectedIndex2 = 0
    
     var body: some View {
                VStack{
                    List{
                            HStack{
                                Text("From")
                                    .foregroundColor(Color("Color"))
                                    .fontWeight(.bold)
                                    .font(.system(size: 20))
                                    .padding(.leading, 10.0)
                                    .frame(width: nil, height: nil, alignment: .leading)
                                Picker(selection: $selectedIndex2, label: Text("")) {
                                    ForEach(0 ..< datas2.cities.count, id: \.self) {
                                        Text(datas2.cities[[=11=]].name)
                                        
                                    }
                                }.foregroundColor(Color("Color"))
                                    .padding(.trailing)
    }
    }
    }
}
    struct City: Codable, Identifiable {
            enum CodingKeys: CodingKey {
                case name
            }
            
            var id = UUID()
            var name: String
        }
        class ReadData2: ObservableObject  {
           @Published var cities = [City]()
           
           
           init(){
               loadData()
           }
           
           func loadData()  {
               guard let url = Bundle.main.url(forResource: "cities", withExtension: "json")
               else {
                   print("Json file not found")
                   return
               }
               
               let data = try? Data(contentsOf: url)
               let cities = try? JSONDecoder().decode([City].self, from: data!)
               self.cities = cities!
               
           }
           
       }

我有一个名为 cities 的 json 文件,它是这样的:

{
    "country": "AD",
    "name": "Sant Julià de Lòria",
    "lat": "42.46372",
    "lng": "1.49129"
  },
  {
    "country": "AD",
    "name": "Pas de la Casa",
    "lat": "42.54277",
    "lng": "1.73361"
  },
  {
    "country": "AD",
    "name": "Ordino",
    "lat": "42.55623",
    "lng": "1.53319"
  },
  {
    "country": "AD",
    "name": "les Escaldes",
    "lat": "42.50729",
    "lng": "1.53414"
  },
  {
    "country": "AD",
    "name": "la Massana",
    "lat": "42.54499",
    "lng": "1.51483"
  },

我的问题是引用的数据太多,一旦我按下选择器,读取数据需要很长时间,post选择器中的数据,有没有更好的方法让它更快?
我正试图通过使用城市首字母的搜索文本使其可搜索,但它不起作用! 我希望你能帮助我!

对于大量项目,我建议使用针对此优化的 ListLazyVStack,而不是 Picker。 类似于以下示例代码。 请注意,您必须根据自己的目的调整 UI。

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

struct Test: View {
    @StateObject var datas2 = ReadData2()
    @State var selectedCity: City?
    @State private var searchQuery: String = ""
    
    var body: some View {
        VStack (spacing: 20) {
            TextField("city search", text: $searchQuery).padding(5)
                .overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.blue, lineWidth: 1))
                .foregroundColor(.blue)
                .frame(width: 160)
                .padding(.top, 20.0)
            
            HStack {
                Text("From")
                    .fontWeight(.bold)
                    .font(.system(size: 20))
                    .padding(.leading, 10.0)
                Spacer()
                ScrollView {
                    LazyVStack {
                        ForEach(datas2.cities.filter{searchFor([=10=].name)}.sorted(by: { [=10=].name < .name })) { city in
                            Text(city.name).foregroundColor(selectedCity == city ? .red : .blue)
                                .onTapGesture {
                                    selectedCity = city
                                }
                        }
                    }
                }.frame(width: 222, height: 111)
            }
            Spacer()
        }
    }
    
    private func searchFor(_ txt: String) -> Bool {
        return (txt.lowercased(with: .current).hasPrefix(searchQuery.trimmingCharacters(in: .whitespacesAndNewlines).lowercased(with: .current)) || searchQuery.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
    }
}
struct City: Codable, Identifiable, Hashable {
    enum CodingKeys: CodingKey {
        case name
    }

    var id = UUID()
    var name: String
}

class ReadData2: ObservableObject  {
    @Published var cities = [City]()
    
    init() {
        loadData()
    }
    
    func loadData() {
        if let url =  Bundle.main.url(forResource: "cities", withExtension: "json") {
            do {
                let data = try Data(contentsOf: url)
                cities = try JSONDecoder().decode([City].self, from: data)
            } catch {
                print(" error:\(error)")
            }
        }
    }
}