Firebase + Swift:removeAllObservers不工作?

时间:2016-11-23 18:47:27

标签: swift firebase firebase-realtime-database

我有2个引用(对于相同的路径),一个用于侦听挂起的订单,另一个用于侦听已完成的订单。全部用于特定位置,用户可以更改。

我现在使用的机制是:

  1. 创建一个存储Firebase参考的数组
  2. 在我observe待处理订单的事件之前,将Firebase引用推送到我的数组
  3. 在我observe完成订单的事件之前,将Firebase引用推送到我的数组
  4. 当用户切换其位置时,删除阵列中所有引用的所有观察者。清空阵列并开始在新位置(步骤2和3)中侦听待处理/已完成的订单
  5. 我的代码如下所示:

    struct Firebase {
    
      private let ORDERS_PATH = "locations-orders"
    
      private static var references = [FIRDatabaseReference]()
    
      static func observePendingOrders(lId: String, f: @escaping (AppState.Order) -> () ) {
        print("observing orders for \(ORDERS_PATH)/\(lId)")
    
        let pendingOrdersReference = FIRDatabase.database().reference(withPath: "\(ORDERS_PATH)/\(lId)")
        self.references.append(pendingOrdersReference)
    
        pendingOrdersReference
          .child(dateKeyToday())
          .queryOrdered(byChild: "created_at")
          .observe(.childAdded, with: { firebaseSnapshot in
            ...
    
            print("order received for \(ORDERS_PATH)/\(lId)")
          }
        )
      }
    
      static func fetchCompletedOrders(lId: String, f: @escaping ([AppState.Order]) -> () ) {
        print("observing completed orders for \(lId)")
    
        let completedOrdersReference = FIRDatabase.database().reference(withPath: "\(ORDERS_PATH)/\(lId)")
        self.references.append(completedOrdersReference)
    
        completedOrdersReference
          .child(dateKeyToday())
          .queryOrdered(byChild: "status_updated_at")
          .observe(.value, with: { firebaseSnapshot in
            ...
          }
        )
      }
    
      static func removeAllOrderObservers() {
        for reference in references {
          print("removing reference \(reference)")
          reference.removeAllObservers()
        }
        self.references = []
      }
    
    }
    

    然而,当我记录我正在观看的订单的位置时,看起来即使我切换位置后,旧的观察者仍在监听订单。这是我的日志:

    observing orders for locations-orders/9RC4H9ZAE457E // first location
    observing completed orders for 9RC4H9ZAE457E
    removing reference https://mydb-123.firebaseio.com/locations-orders/9RC4H9ZAE457E // switch locations, remove all existing observers for location 9RC4H9ZAE457E
    removing reference https://mydb-123.firebaseio.com/locations-orders/9RC4H9ZAE457E
    observing orders for locations-orders/1JS53G0TT5ZQD // start listening for orders in new location. notice the new id: 1JS53G0TT5ZQD
    observing completed orders for 1JS53G0TT5ZQD
    order received for locations-orders/9RC4H9ZAE457E // <-- why is this still showing up?
    order received for locations-orders/1JS53G0TT5ZQD
    order received for locations-orders/1JS53G0TT5ZQD
    order received for locations-orders/9RC4H9ZAE457E // <-- and this one too??
    order received for locations-orders/1JS53G0TT5ZQD
    order received for locations-orders/1JS53G0TT5ZQD
    

    ===更新=== 我甚至试过手柄,它没有工作:

    struct Firebase {
    
      private static var handles = [UInt]()
      private static var references = [FIRDatabaseReference]()
    
      static func observePendingOrders(lId: String, f: @escaping (AppState.Order) -> () ) {
        print("observing orders for \(ORDERS_PATH)/\(lId)")
    
        let pendingOrdersReference = FIRDatabase.database().reference(withPath: "\(ORDERS_PATH)/\(lId)")
        self.references.append(pendingOrdersReference)
    
        let handle = pendingOrdersReference
          .child(dateKeyToday())
          .queryOrdered(byChild: "created_at")
          .observe(.childAdded, with: { firebaseSnapshot in
            ...
          }
        )
    
        handles.append(handle)
      }
    
      static func fetchCompletedOrders(lId: String, f: @escaping ([AppState.Order]) -> () ) {
        print("observing completed orders for \(ORDERS_PATH)/\(lId)")
    
        let completedOrdersReference = FIRDatabase.database().reference(withPath: "\(ORDERS_PATH)/\(lId)")
        self.references.append(completedOrdersReference)
    
        let handle = completedOrdersReference
          .child(dateKeyToday())
          .queryOrdered(byChild: "status_updated_at")
          .observe(.value, with: { firebaseSnapshot in
            ...
          }
        )
        handles.append(handle)
      }
    
      static func removeAllOrderObservers() {
    //    for reference in references {
    //      print("removing reference \(reference)")
    //      reference.removeAllObservers()
    //    }
    //    
        if !references.isEmpty {
          let ref = references[0]
          for handle in handles {
            print("removing handle \(handle)")
            ref.removeObserver(withHandle: handle)
          }
          self.references = []
        }
      }
    }
    

1 个答案:

答案 0 :(得分:0)

我想我可能已经修好了吗?所以这是因为我实际上正在观察该引用的子节点,因此删除父节点的所有观察者都没有做任何事情,因为你必须在你正在观察的特定节点上删除它。

let pendingOrdersReference = FIRDatabase
  .database()
  .reference(withPath: "\(ORDERS_PATH)/\(lId)")
  .child(dateKeyToday()) // <---- added this thing

这是我的最终解决方案,似乎有效:

struct Firebase {
  private static var references = [FIRDatabaseReference]()

  static func observePendingOrders(lId: String, f: @escaping (AppState.Order) -> () ) {
    print("observing orders for \(ORDERS_PATH)/\(lId)")

    let pendingOrdersReference = FIRDatabase
      .database()
      .reference(withPath: "\(ORDERS_PATH)/\(lId)")
      .child(dateKeyToday())
    self.references.append(pendingOrdersReference)

    ...
  }

  static func fetchCompletedOrders(lId: String, f: @escaping ([AppState.Order]) -> () ) {
    print("observing completed orders for \(ORDERS_PATH)/\(lId)")

    let completedOrdersReference = FIRDatabase
      .database()
      .reference(withPath: "\(ORDERS_PATH)/\(lId)")
      .child(dateKeyToday())
    self.references.append(completedOrdersReference)

    ...

  }

  static func removeAllOrderObservers() {
    for reference in references {
      print("removing reference \(reference)")

      reference.removeAllObservers()
    }
    self.references = []
  }

}