阅读 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选择器中的数据,有没有更好的方法让它更快?
我正试图通过使用城市首字母的搜索文本使其可搜索,但它不起作用!
我希望你能帮助我!
对于大量项目,我建议使用针对此优化的 List
或 LazyVStack
,而不是 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)")
}
}
}
}
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选择器中的数据,有没有更好的方法让它更快?
我正试图通过使用城市首字母的搜索文本使其可搜索,但它不起作用!
我希望你能帮助我!
对于大量项目,我建议使用针对此优化的 List
或 LazyVStack
,而不是 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)")
}
}
}
}