【问题标题】:Filter Firebase Data SwiftUI过滤 Firebase 数据 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
                    }
                }
            }
        }
    }
}

}

【问题讨论】:

    标签: swift firebase google-cloud-firestore swiftui


    【解决方案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,非常感谢您抽出宝贵的时间。不,绝对不需要分隔数组。实际上,我尝试通过单个数组中的查询来解决它,但我做不到。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-17
    • 2019-08-12
    • 2019-03-24
    • 1970-01-01
    • 2020-07-19
    • 2019-04-10
    相关资源
    最近更新 更多