我有一个Category类的数组,该类具有名称和parentName。我有一个搜索栏,允许用户通过类别名称或parentName搜索类别。我的全套产品大约有600件。键入第一个字母大约需要2-3秒,并冻结键盘上的所有其他输入。在第一个字母之后,一切都很快。
这是我的过滤方式
return self.userData.categories.filter({$0.name.lowercased().hasPrefix(searchText.lowercased()) || ($0.parentName != nil && $0.parentName!.lowercased().hasPrefix(searchText.lowercased()))})
我想可能是SwiftUI渲染所有行,但是初始渲染很快。
这就是我呈现类别的方式。
List(categories) { category in
CategoryPickerRowView(category: category, isSelected: category.id == self.transaction.categoryId)
.onTapGesture { self.transaction.categoryId = category.id }
}
更新: 我注意到键入或删除第一个字母时(速度很慢时),我在日志中收到此消息
[快照]快照至少一次未呈现的视图(0x7fb6bd4b8080,_UIReplicantView)需要afterScreenUpdates:YES。
答案 0 :(得分:1)
您可以使用“合并”对搜索进行反跳操作,以便仅在用户停止键入后才进行搜索。您还可以使用合并将过滤器移至后台,然后将分配移回主队列。
class Model: ObservableObject {
@Published var searchResults: [String] = []
let searchTermSubject = CurrentValueSubject<String, Never>("")
let categorySubject = CurrentValueSubject<String, Never>("")
private var subscriptions = Set<AnyCancellable>()
init() {
Publishers
.CombineLatest(
searchTermSubject
.debounce(for: .milliseconds(250), scheduler: RunLoop.main),
categorySubject
)
.receive(on: DispatchQueue.global(qos: .userInteractive))
.map { combined -> [String] in
// Do search here
}
.receive(on: RunLoop.main)
.assign(to: \.searchResults, on: self)
.store(in: &subscriptions)
}
}
答案 1 :(得分:1)
通过将.id(UUID())
添加到列表中,可以解决此问题。
List(categories) { category in
CategoryPickerRowView(category: category, isSelected: category.id == self.transaction.categoryId)
.onTapGesture { self.transaction.categoryId = category.id }
}.id(UUID())
在此处找到说明:https://www.hackingwithswift.com/articles/210/how-to-fix-slow-list-updates-in-swiftui
答案 2 :(得分:-1)
使用文本字段委托:-
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool
{
if string.isEmpty
{
search = String(search.dropLast())
}else{
search=textField.text!+string
}
并使用“ .contain”搜索名称。 例如:-
var search:String = ""
var searchData:NSArray?
let filtered = rewardArray?.filter { ($0.name .lowercased()).contains(search.lowercased()) }
searchData = filtered as NSArray?
并使用searchData重新加载您的集合或表