如何实现点击键盘搜索按钮后再执行列表过滤?
解决实时搜索卡顿:改为点击搜索按钮再执行搜索
你的问题核心在于当前每输入一个字符就会触发searchTerm更新,进而导致List实时执行全量过滤——如果数据集较大,这种频繁计算必然会引发卡顿。我们可以通过分离输入文本和过滤触发时机来彻底解决这个问题,具体实现步骤如下:
1. 修改SearchBar组件,添加搜索按钮回调
先给自定义的SearchBar新增一个闭包参数,用来在用户点击搜索按钮时通知父视图执行搜索。同时我们可以添加取消按钮的处理,进一步提升用户体验:
import Foundation import SwiftUI struct SearchBar: UIViewRepresentable { @Binding var text: String var placeholder: String // 新增:搜索按钮点击的回调闭包,用于通知父视图执行搜索 var onSearchTriggered: (String) -> Void class Coordinator: NSObject, UISearchBarDelegate { @Binding var text: String let onSearchTriggered: (String) -> Void init(text: Binding<String>, onSearchTriggered: @escaping (String) -> Void) { _text = text self.onSearchTriggered = onSearchTriggered } // 保持实时同步搜索栏输入文本,但不触发过滤逻辑 func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { text = searchText } // 点击搜索按钮时,触发父视图的搜索逻辑并收起键盘 func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { onSearchTriggered(text) searchBar.resignFirstResponder() } // 点击取消按钮时,清空输入内容和过滤条件 func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { text = "" onSearchTriggered("") searchBar.resignFirstResponder() } } func makeCoordinator() -> Coordinator { Coordinator(text: $text, onSearchTriggered: onSearchTriggered) } func makeUIView(context: Context) -> UISearchBar { let searchBar = UISearchBar(frame: .zero) searchBar.delegate = context.coordinator searchBar.placeholder = placeholder searchBar.searchBarStyle = .minimal searchBar.autocapitalizationType = .none searchBar.showsCancelButton = true // 显示取消按钮,优化操作体验 return searchBar } func updateUIView(_ uiView: UISearchBar, context: Context) { uiView.text = text } }
2. 调整ContentView,分离输入与过滤逻辑
在ContentView中新增一个专门用于过滤的变量,只有在用户点击搜索按钮时才更新它,这样List的过滤操作只会在需要的时候执行:
struct ContentView: View { @State private var searchInput = "" // 实时同步搜索栏输入的文本 @State private var activeSearchTerm = "" // 实际用于过滤的文本,仅在点击搜索时更新 // 替换成你的实际数据模型类型 let gesetzestextTEMPO: [YourDataModel] = [] // 提取过滤逻辑为计算属性,让代码更整洁易维护 private var filteredItems: [YourDataModel] { gesetzestextTEMPO.filter { item in guard !activeSearchTerm.isEmpty else { return true } let lowercasedSearch = activeSearchTerm.localizedLowercase return item.titel1.localizedLowercase.contains(lowercasedSearch) || item.artikel.localizedLowercase.contains(lowercasedSearch) || item.marginale.localizedLowercase.contains(lowercasedSearch) || item.absatz0.localizedLowercase.contains(lowercasedSearch) || item.absatz0litaz.localizedLowercase.contains(lowercasedSearch) } } var body: some View { VStack { SearchBar(text: $searchInput, placeholder: "Suche") { searchText in // 点击搜索按钮时,更新过滤用的文本 activeSearchTerm = searchText } } List { ForEach(filteredItems) { item in Part13(gesetzestextTEMPO: item, searchTerm: $activeSearchTerm) } } } }
核心原理说明
- 输入与过滤解耦:
searchInput仅负责同步用户在搜索栏的输入,不会触发List的过滤;activeSearchTerm才是驱动List过滤的变量,只有点击搜索按钮时才会更新。 - 减少不必要计算:原来每次输入字符都会执行一次全量过滤,现在只有在用户明确点击搜索时才执行一次,大幅减少了性能消耗。
- 用户体验优化:添加取消按钮,让用户可以快速清空搜索状态,操作更流畅。
内容的提问来源于stack exchange,提问作者iSoldier
相关产品推荐
相关产品推荐

