You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 11:52:34