通过大型 Array Swift 过滤
Posted
技术标签:
【中文标题】通过大型 Array Swift 过滤【英文标题】:Filter through large Array Swift 【发布时间】:2021-05-18 03:26:22 【问题描述】:我正在构建一个旅行计划应用程序,它允许用户使用 Picker 从本地 json 文件中选择一个城市。
json 文件有 115K 项,如果我尝试过滤这么多项,UI 会冻结。有关如何提高效率的任何建议。
任何帮助将不胜感激。
import SwiftUI
struct AddTripView: View
let cities = Bundle.main.decode([Destination].self, from: "cities.json")
@State private var selectedCity = 0
@State var searchText = ""
var body: some View
Form
Section
Picker(selection: $selectedCity, label: Text("Select city"))
SearchBar(text: $searchText)
ForEach(cities.filter searchText.isEmpty ? true : $0.city.lowercased().hasPrefix(searchText.lowercased()), id: \.self)
Text($0.city)
.navigationBarTitle("Create trip")
struct AddTripView_Previews: PreviewProvider
static var previews: some View
AddTripView()
JSON 示例
[
"id": 1,
"city": "Zaranj",
"country": "Afghanistan"
,
"id": 2,
"city": "Taloqan",
"country": "Afghanistan"
,
"id": 3,
"city": "Shīnḏanḏ",
"country": "Afghanistan"
,
"id": 4,
"city": "Shibirghān",
"country": "Afghanistan"
,
"id": 5,
"city": "Shahrak",
"country": "Afghanistan"
]
【问题讨论】:
有一个运算符来表示? true :
。看底部here;这是||
。
将过滤移至后台线程并改为显示虚拟数据,直到数据可用。也许你可以使用@State 来了解它的状态
许多事情:将逻辑提取到视图模型中,在后台解码一次 json,对输入的搜索文本使用 debounce(如***.com/a/66186675/12299030),在后台执行过滤(如***.com/a/67135819/12299030),等等
将 json 导入只读 SQLite 或 Core Data 存储库是另一种选择。数据库非常适合这种情况,因为您有大量数据并且需要进行过滤/搜索
【参考方案1】:
您真的需要选择器吗?如果没有,你可以试试这个例子。 如果 UI 仍然存在问题,请告诉我们。
struct AddTripView: View
@State private var cities = [Destination]()
@State private var selectedCity: Destination?
@State private var searchQuery: String = ""
var body: some View
VStack
Text("\(cities.count)")
HStack
TextField("city search", text: $searchQuery).padding(5)
.overlay(RoundedRectangle(cornerRadius: 15).stroke(Color.blue, lineWidth: 1))
.foregroundColor(.blue)
.frame(width: 160)
Button(action: searchQuery = "")
Image(systemName: "xmark.circle").font(.title)
.padding(20)
Divider()
Text("Select city")
ScrollView
LazyVStack (alignment: .leading)
ForEach(cities.filterself.searchFor($0.city).sorted(by: $0.city < $1.city )) city in
Text("\(city.city) \(city.country)")
.onTapGesture
selectedCity = city
print("---> selectedCity: \(selectedCity?.city)")
.onAppear()
cities = Bundle.main.decode([Destination].self, from: "cities.json")
private func searchFor(_ txt: String) -> Bool
return (txt.lowercased(with: .current).hasPrefix(searchQuery.lowercased(with: .current)) || searchQuery.isEmpty)
struct Destination: Codable, Identifiable, Equatable
var id: Int
var city: String
var country: String
【讨论】:
谢谢我喜欢这种方法,虽然 UI 仍然冻结。 我已经使用 ScrollView 和 LazyVStack 而不是 List 更新了代码。它似乎反应灵敏得多。你觉得怎么样?以上是关于通过大型 Array Swift 过滤的主要内容,如果未能解决你的问题,请参考以下文章