过滤 Firebase 数据 SwiftUI
Posted
技术标签:
【中文标题】过滤 Firebase 数据 SwiftUI【英文标题】:Filter Firebase Data SwiftUI 【发布时间】:2020-04-24 13:23:10 【问题描述】:此代码将所有数据添加到单个数组中。在 HomeViev 中,我使用 Foreach 并将数据添加到列表中。但我必须将数据一分为二。状态集合有两种类型“活动”和“关闭”,但我不知道如何过滤
import SwiftUI
import Combine
import Firebase
let dbCollection = Firestore.firestore().collection("Signals")
class FirebaseSession : ObservableObject
@Published var session: User? didSet self.didChange.send(self)
@Published var data = [Signal]()
var didChange = PassthroughSubject<FirebaseSession, Never>()
var handle: AuthStateDidChangeListenerHandle?
func listen ()
handle = Auth.auth().addStateDidChangeListener (auth, user) in
if let user = user
print("Got user: \(user)")
self.session = User(uid: user.uid, email: user.email)
self.readData()
else
self.session = nil
func readData()
dbCollection.addSnapshotListener (documentSnapshot, err) in
if err != nil
print((err?.localizedDescription)!)
return
else
print("read data success")
documentSnapshot!.documentChanges.forEach i in
// 从服务器读取实时创建的数据
if i.type == .added
let id = i.document.documentID
let symbol = i.document.get("symbol") as? String ?? ""
let status = i.document.get("status") as? String ?? ""
self.data.append(Signal(id: id, symbol: symbol, status: status))
// 从服务器读取实时修改数据
if i.type == .modified
self.data = self.data.map (eachData) -> Signal in
var data = eachData
if data.id == i.document.documentID
data.symbol = i.document.get("symbol") as! String
data.status = i.document.get("status") as? String ?? ""
return data
else
return eachData
// 当数据被删除时...
if i.type == .removed
let id = i.document.documentID
for i in 0..<self.data.count
if self.data[i].id == id
self.data.remove(at: i)
return
【问题讨论】:
【参考方案1】:问题陈述
但我必须将数据一分为二
我假设这意味着两个数组;一个是活动的,一个是关闭的。
var activeData = [...
var closedData = [...
有几种方法可以做到这一点
1) 在 Firestore 中查询所有等于 active 的状态字段并将这些文档加载到 active 数组中,然后再查询等于 closed 的状态字段并将其加载到 closed 数组中
2) 我会建议一个更简单的方法
if i.type == .added
let id = i.document.documentID
let symbol = i.document.get("symbol") as? String ?? ""
let status = i.document.get("status") as? String ?? ""
if status == "active"
self.activeData.append(Signal(id: id, symbol: symbol, status: status))
else
self.closedData.append(Signal(id: id, symbol: symbol, status: status))
在 .modified 和 .removed 中做同样的事情;识别状态,以便代码知道从哪个数组中删除它。
编辑:
基于评论
我不知道如何查询这些代码。
我正在提供代码来查询活动的信号。此代码将仅返回活动信号,并且当信号变为活动、非活动等时,这将修改 signalArray 以与数据保持同步。
let dbCollection = Firestore.firestore().collection("Signals")
let query = dbCollection.whereField("status", isEqualTo: "active").addSnapshotListener( querySnapshot, error in
guard let snapshot = querySnapshot else
print("Error fetching snapshots: \(error!)")
return
snapshot.documentChanges.forEach diff in
if (diff.type == .added)
let signalToAdd = Signal(withDoc: diff.document)
self.signalArray.append(signalToAdd)
if (diff.type == .modified)
let docId = diff.document.documentID
if let indexOfSignalToModify = self.signalArray.firstIndex(where: $0.signal_id == docId )
let signalToModify = self.signalArray[indexOfSignalToModify]
signalToModify.updateProperties(withDoc: diff.document)
if (diff.type == .removed)
let docId = diff.document.documentID
if let indexOfSignalToRemove = self.signalArray.firstIndex(where: $0.signal_id == docId )
self.signalArray.remove(at: indexOfSignalToRemove)
)
请注意,我的 Signal 类有一个初始化程序,它接受一个 QueryDocumentSnapshot 来初始化它,以及一个 .updateProperties 函数来更新它的内部属性。
【讨论】:
谢谢Jay,我试过第一种方法,但没有。我尝试了你的第二种方法,但不幸的是它不起作用。 @John 这两个选项对我们都很有效,第二个选项更简单。说“它不起作用”并不能真正告诉我们什么不起作用。您能否更新您的问题以显示不起作用的代码? 抱歉@Jay,您的解决方案运行良好,非常感谢。问题是关于数据库规则的。你能帮我处理 .modified 和 .removed 吗? @John Sure... .modified 中的代码有点奇怪...您需要在那里执行您在 .deleted 中所做的操作。您需要找到已修改的匹配项,然后使用新数据更新该字段。如果你这样做,那么你可以使用我在 . added 部分中使用的相同格式,除了如果它从活动更改为关闭,你需要从添加的数组中删除它。在我更新答案之前,您真的需要两个单独的数组吗?一个用于活动,一个用于关闭,或者您可以将它们保留在同一个数组中并使用其他代码来过滤活动和关闭的信号吗? 嗨@Jay,非常感谢您抽出宝贵的时间。不,绝对不需要分隔数组。实际上,我尝试通过单个数组中的查询来解决它,但我做不到。以上是关于过滤 Firebase 数据 SwiftUI的主要内容,如果未能解决你的问题,请参考以下文章
Firebase、Flutter - 读取、检索过滤后的数据