从UITableViewCell清除Firebase观察

问题描述 投票:2回答:2

在使用Firebase的所有iOS类中,您将拥有这样的代码,

private func clearObservations() {

    // your method for clearing observations, probably something like
    blah blah. removeAllObservers()
}

在视图控制器中,您必须在viewWillDisappear(或viewDidDisappear)中调用它

override func viewWillDisappear(_ animated: Bool) {

    super.viewWillDisappear(animated)
    clearObservations()
}

没关系。

假设您已在UITableViewCell中创建了一个观察。

细胞中“清除观察”的最佳位置是什么?

请注意,prepareForReuse没用,试试吧。

我们发现的唯一方法是

override func willMove(toSuperview newSuperview: UIView?) {

    if newSuperview == nil {

        clearObservations()
    }
    super.willMove(toSuperview: newSuperview)
}

虽然看似flakey / bizarre。

这是什么交易?


请注意,虽然“XY答案”很有趣并且内容丰富,但如果有人知道这个问题的答案也会很棒!圣诞快乐

ios uitableview firebase firebase-realtime-database
2个回答
1
投票

编辑:

这是试图回答这个问题,但这个问题被误解了。我会把它留在这里,因为它确实与观察者,句柄和tableView单元格交互有关。

--

虽然你可以通过这些旋转,但在大多数用例中并不是真的需要它。

例如,如果向节点添加和观察者,则不一定有someRef?变数徘徊。所以我们在这里观看Posts节点的新帖子

let postsRef = self.ref.child("Posts")
postsRef.observe(.childAdded, with: { snapshot in
    print(snapshot) //add the post to the dataSource and reloadTableview/cell
})

这是另一个观看由uid_2更改的帖子的示例

let postsRef = self.ref.child("Posts")
let queryRef = postsRef.queryOrdered(byChild: "poster_id").queryEqual(toValue: "uid_2")
queryRef.observe(.childChanged) { (snapshot) in
    print(snapshot) //change the post in the dataSource and reloadTableview/cell
}

此功能不需要类变量,也不需要任何内容​​。这里的要点是你不必拥有类变量以获得观察功能,而且你不需要为每个观察者保留一个句柄(继续阅读)

在视图控制器中,必须在viewWillDisappear(或Did)中调用它(someRef?.removeAllObservers())..将在表格的单元格中使用Firebase。

澄清;我不想将Firebase观察者放在表格的单元格中。观察者应该在viewController中控制具有单元格的tableView。单元格应从dataSource数组(由Firebase支持)中提取数据

在某些情况下,您可能希望删除所有观察者,同样不需要具有类var或需要nil var。

let postsRef = self.ref.child("Posts")
postsRef.removeAllObservers()

有时需要删除特定的观察者(例如,节点在其子节点上有观察者的情况下),在这种情况下,我们将一个句柄存储到该观察者,例如,一个类var(保持它们)一个数组是一个整洁的方式来做到这一点)

class ViewController: UIViewController {
   var myPostHandle : DatabaseHandle?

   func addObserver() {
      let postsRef = self.ref.child("Posts")
      self.myPostHandle = postsRef.observe(.childAdded, with: { snapshot in
         print(snapshot)
      })

   func stopObserving() {
      if self.myPostHandle != nil {
         let postsRef = self.ref.child("Posts")
         postsRef.removeObserver(withHandle: self.myPostHandle) //remove only the .childAdded observer
      }
   }
}

但是,一旦观察者被移除,一旦课程关闭,句柄就会超出范围。

包含单元格的表视图由dataSource支持,dataSource从firebase获取它的数据。当从Firebase添加,更改或删除某些内容时,会通知您的应用并更新阵列,然后刷新单元格。细胞本身不需要观察者。

没有必要添加几十个观察者(在单元格中) - 添加一个中心观察者并让它保持阵列最新。只有在发生变化时才刷新tableView。

编辑

要解决有关使用removeAllObservers的注释:代码值1000字:

使用两个按钮操作创建一个新的Firebase项目。这是button0的代码,它将观察者添加到节点:

func button0() {   
    let testRef = self.ref.child("test_node")
    testRef.observe( .value) { snapshot in
        print(snapshot)
    }
}

单击此按钮0时,从那里开始,对测试节点的任何添加,更改或删除都会将其内容打印到日志中。

func button1() {   
    let testRef = self.ref.child("test_node")
    testRef.removeAllObservers()
}

这将删除指定节点的所有观察者。单击后,将不会向控制台打印任何事件。

试试吧!


-1
投票

清除细胞中的观察结果是不对的,因此在细胞中没有最好的位置,因为,首先,这种方法与MVC模式相矛盾。视图仅负责显示内容,它们应仅包含描述必须如何绘制的代码。在视图控制器中,您可以提供按视图显示的内容。通常内容由您的模型提供。因此控制器连接视图和模型。在您的情况下,当您在单元类中放置clearObservations()时,您还将someRef作为类属性,因此您在视图类中有一个模型,这是不正确的。

其次,如果你试图清除表格单元格中的观察结果,你肯定会错误地在表格中显示某些内容。 Cell仅显示必须由符合UITableViewDataSource协议并实现协议方法的某个对象生成的数据。例如,在cellForRow方法中,您生成单元格并使用数组中的某些内容设置它。此数组是从模型(Firebase服务)生成的。您的视图控制器可能是此数据源对象。您必须包含数组属性到控制器类和someRef,而不是填充数组和重新加载表数据。如果控制器的视图消失,则清除观察结果,但只在视图控制器内部(在viewWillDisappear()中)执行。

总的来说,所有使用someRef的操作都应该在视图控制器中完成,因此在控制器内也可以进行“清晰观察”。

© www.soinside.com 2019 - 2024. All rights reserved.