SwiftUI 中的 “searchable in Model()” 可以翻译为 “在模型中可搜索”。

huangapple go评论62阅读模式
英文:

SwiftUI searchable in Model()

问题

I've translated the content you provided, focusing on the code parts as you requested. Here's the translated code:

我在使用SwiftUI的Searchable时遇到问题,用于我的数据模型。我从Firestore读取了数据,并保存为GBplayerModel()中的数组。

使用Searchable时,它可以过滤球员列表,但在移除搜索文本时不会返回原始列表视图。

基本上,我希望主视图是可以搜索的完整列表。

数据模型

import Foundation
import Firebase

struct GBplayer: Identifiable {
    var id: String
    var name: String
    var status: String
    var height: String
    var team: String
    var position: String
}

// 用于预览的模拟数据
extension GBplayer {
    static func mock() -> GBplayer {
        GBplayer(id: "Aaron Menzies", name: "Aaron Menzies", status: "Active", height: "7ft 3", team: "Leicester Riders", position: "C")
    }
}

class GBplayerModel: ObservableObject {
    
    @Published var playerList = [GBplayer]()
    
    func getGBplayers() {
           
        // 获取数据库引用
        let db = Firestore.firestore()
        
        db.collection("GBplayers").getDocuments { snapshot, error in
            
            // 检查错误
            if error == nil {
                // 没有错误
                print("您已登录")
                
                if let snapshot = snapshot {
                    
                    // 在主线程中更新列表属性
                    DispatchQueue.main.async {
                        
                        // 获取所有文档并创建球员列表
                        self.playerList = 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 ?? "")
                        }
                    }
                }
            } else {
                // 处理错误
                print("没有文档")
                return
            }    
        }   
    }    
}

视图

import SwiftUI

struct playerView: View {
    
    @ObservedObject var model = GBplayerModel()
    @State private var searchPlayer = ""
    
    var body: some View {
        
        NavigationView {
            
            List {
                ForEach (model.playerList) { player in
                    
                    NavigationLink  {
                        Text("详细视图")   // 需要在此处添加详细视图
                    } label: {
                        PlayerRow(player: player)
                    }
                }
            }
            .listStyle(.plain)
            .navigationTitle("球员")
            
            // 从Firebase更新数据
            .onAppear() {
                self.model.getGBplayers()                
            }
            
            .searchable(text: $searchPlayer, placement: .navigationBarDrawer(displayMode: .always), prompt: "查找球员")
            
            .onChange(of: searchPlayer) { search in
                if !search.isEmpty {model.playerList = model.playerList.filter { $0.name.contains(searchPlayer) }
                } else {
                    model.playerList = model.playerList
                }
            }
        }  
    }
}

I hope this helps! If you have any further questions or need assistance with specific parts of the code, feel free to ask.

英文:

I am having issues using searchable in SwiftUI for my data model. I have read the data from firestore and saved as an array in GBplayerModel().

When using searchable it filters the list of players but won't go back to the original list view when the search text is removed.

Essentially I want to main view be the full list that can be searched through.

Data Model

    import Foundation
import Firebase
struct GBplayer: Identifiable {
var id: String
var name: String
var status: String
var height: String
var team: String
var position: String
}
// mock data that we can use for previews  
extension GBplayer {
static func mock()  -> GBplayer {
GBplayer(id: "Aaron Menzies", name: "Aaron Menzies", status: "Active", height: "7ft 3", team: "Leicester Riders", position: "C")
}
}
class GBplayerModel: ObservableObject {
@Published var playerList = [GBplayer]()
func getGBplayers() {
// get reference to the db
let db = Firestore.firestore()
db.collection("GBplayers").getDocuments { snapshot, error in
//check for errors
if error == nil {
// no errors
print("your in")
if let snapshot = snapshot {
// Update the list property in the main thread
DispatchQueue.main.async {
// get all the documents and create list of players
self.playerList = snapshot.documents.map { d in
//create a player struc for each player in the document
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 ?? "",
}
}
}
} else {
// handle the error
print("No Documents")
return
}    
}   
}    
}

View

import SwiftUI
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")   //need to add detailed view here     
} label: {
PlayerRow(player: player)
}
}
}
.listStyle(.plain)
.navigationTitle("Players")
// update data from Firebase 
.onAppear() {
self.model.getGBplayers()                
}
.searchable(text: $searchPlayer, placement: .navigationBarDrawer(displayMode: .always), prompt: "Find a player")
.onChange(of: searchPlayer) { search in
if !search.isEmpty {model.playerList = model.playerList.filter { $0.name.contains(searchPlayer) }
} else {
model.playerList = model.playerList
}
}
}
}  
}

Any help would be greatly appreciated, spent a lot time of this and appreciate it maybe something simple

答案1

得分: 1

现在,当您搜索时,您正在改变您的 playerList,当您执行以下操作时:

model.playerList = model.playerList.filter { ... }

这意味着如果您更改搜索词(或者将其删除),那些被过滤掉的项目将不再存在。

相反,您应该始终保留完整的 playerList,并且只 显示 一个经过筛选的版本:

var filteredList: [GBplayer] {
  if search.isEmpty {
    return model.playerList
  } else {
    return model.playerList.filter { ... }
  }
}
// ...

ForEach(filteredList) { player in ... }

然后删除您的 onChange 代码。

英文:

Right now, when you search, you're mutating your playerList when you do this:

model.playerList = model.playerList.filter { ... }

That means that if you change your search term (or get rid of it), the items that were filtered out no longer exist.

Instead, you should always keep the full playerList and only display a filtered version:

var filteredList: [GBplayer] {
if search.isEmpty {
return model.playerList
} else {
return model.playerList.filter { ... }
}
}
// ...
ForEach (filteredList) { player in ... }

And remove your onChange code

huangapple
  • 本文由 发表于 2023年4月20日 00:18:38
  • 转载请务必保留本文链接:https://go.coder-hub.com/76056777.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定