SwiftUI中searchable组件无法恢复原始列表问题求助
解决SwiftUI中searchable清除搜索后无法恢复原始列表的问题
你当前的问题核心是直接修改了原始数据源model.playerList:每次执行过滤时,你把playerList替换成了过滤后的子集,导致原始的完整数据被覆盖。当清空搜索文本时,playerList已经是过滤后的结果,再赋值给自己自然无法恢复完整列表。
解决方案思路
在数据模型中单独保存一份原始完整的球员数据,始终基于这份原始数据进行过滤操作,避免修改原始数据源。
1. 修改GBplayerModel数据模型
添加allPlayers属性存储完整原始数据,playerList作为展示用的过滤后数据,同时新增过滤方法:
class GBplayerModel: ObservableObject { @Published var allPlayers = [GBplayer]() // 存储完整原始数据 @Published var playerList = [GBplayer]() // 用于展示的过滤后数据 func getGBplayers() { let db = Firestore.firestore() db.collection("GBplayers").getDocuments { snapshot, error in if error == nil { if let snapshot = snapshot { DispatchQueue.main.async { // 先保存完整原始数据 self.allPlayers = snapshot.documents.map { d in return GBplayer(id: d.documentID, name: d["name"] as? String ?? "", status: d["status"] as? String ?? "", height: d["height"] as? String ?? "", team: d["team"] as? String ?? "", position: d["position"] as? String ?? "", ) } // 初始时展示完整列表 self.playerList = self.allPlayers } } } else { print("No Documents") return } } } // 基于原始数据执行过滤 func filterPlayers(with searchText: String) { if searchText.isEmpty { playerList = allPlayers } else { // 使用localizedCaseInsensitiveContains实现不区分大小写搜索 playerList = allPlayers.filter { $0.name.localizedCaseInsensitiveContains(searchText) } } } }
2. 修改playerView视图
移除原来直接修改playerList的逻辑,改为调用模型的过滤方法:
struct playerView: View { @ObservedObject var model = GBplayerModel() @State private var searchPlayer = "" var body: some View { NavigationView { List { ForEach (model.playerList) { player in NavigationLink { Text("Detailed View") } label: { PlayerRow(player: player) } } } .listStyle(.plain) .navigationTitle("Players") .onAppear() { model.getGBplayers() } .searchable(text: $searchPlayer, placement: .navigationBarDrawer(displayMode: .always), prompt: "Find a player") // 监听搜索文本变化,调用模型的过滤方法 .onChange(of: searchPlayer) { newValue in model.filterPlayers(with: newValue) } } } }
可选简化方案(无需修改模型方法)
如果不想在模型中新增过滤方法,也可以直接在视图中通过计算属性获取过滤结果:
struct playerView: View { @ObservedObject var model = GBplayerModel() @State private var searchPlayer = "" // 计算属性:基于原始数据实时过滤 var filteredPlayers: [GBplayer] { searchPlayer.isEmpty ? model.allPlayers : model.allPlayers.filter { $0.name.localizedCaseInsensitiveContains(searchPlayer) } } var body: some View { NavigationView { List { ForEach (filteredPlayers) { player in NavigationLink { Text("Detailed View") } label: { PlayerRow(player: player) } } } .listStyle(.plain) .navigationTitle("Players") .onAppear() { model.getGBplayers() } .searchable(text: $searchPlayer, placement: .navigationBarDrawer(displayMode: .always), prompt: "Find a player") } } }
内容的提问来源于stack exchange,提问作者Adam Sewell
相关产品推荐
相关产品推荐

