过滤 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 过滤数据与 php

Firebase、Flutter - 读取、检索过滤后的数据

过滤和显示来自 firebase 数据库的搜索栏结果

从 firebase-realtime-database 过滤数据

如何查询和过滤 Firebase 实时数据库 [重复]

Firebase Firestore - 使用多个“数组包含”过滤数据