【问题标题】:Firebase observer architectureFirebase 观察者架构
【发布时间】:2018-09-16 20:47:13
【问题描述】:

好的,所以我正在尝试构建一个依赖 Firebase 的 iOS 应用(使用它的 android 版本)

我开始为我的应用程序中的每个参与者创建一个存储库,并创建一个通用存储库来管理它们

每个存储库都管理该参与者的观察者。一个例子:

在 PagesRepository 中,这是一个从 Firebase 检索所有页面并在 completionHandler 中返回的函数:

//MARK: Gets the whole pages list
func getPagesList(completionHandler: @escaping (_ pages: [Page]?, _ error: NSError?) -> Void) {

    func displayError(error: String) {
        print(error)
        completionHandler(nil, self.getErrorFromString(error))
    }

    pagesRef.observe(DataEventType.value) { pagesSnapshot in

        guard pagesSnapshot.exists() else {
            displayError(error: "Pages snapshot doesn't exist")
            return
        }

        var pagesList = [Page]()
        for pageSnapshot in pagesSnapshot.children {
            pagesList.append(Page(snapshot: pageSnapshot as! DataSnapshot))
        }
        completionHandler(pagesList, nil)
    }
}

然后我像这样从 ViewController 调用它:

repository.getPagesList { (pages, error) in
        guard error == nil else {
            return
        }

        //Do processing
    }

我知道这可能需要考虑很多,但是我的问题是,每次我调用该函数时,它都会创建一个新的观察者,但不会取消旧的观察者......所以,completionHandler 是用不同的值多次调用

我应该如何处理这个问题? (对不起,有点复杂,有点不清楚,我真的迷路了)

【问题讨论】:

  • 不要这样做——它不会起作用,而且很难维护。 Firebase 是异步的,您应该在闭包内 使用快照数据(填充数组,然后更新 UI)。调用 Firebase 观察方法期望它们以这种方式返回数据会使您的 UI 变得怪异。不清楚为什么 getPagesList 被一遍又一遍地调用——Firebase 通常不是这样工作的;您应该让 Firebase 完成繁重的工作,并在添加、更改或删除新数据时通知您。此外,pages 数组似乎是一个类 var (?),因此没有理由传递它。
  • 我认为没有足够的信息来真正正确地回答这个问题;虽然有一个答案,但它可能不是这个用例的正确答案。你为什么反复调用 getPagesList ?为什么要使用完成处理程序而不是将代码放入闭包中?你在用 pagesList 数组做什么 - 它是 tableView 数据源还是其他东西?你为什么要包含一个打印错误的函数,而错误可以直接打印出来?
  • @Jay 其实可以直接放,但是我想把数据代码和UI代码分开。这只是一个架构决策

标签: ios swift firebase firebase-realtime-database swift4


【解决方案1】:

您似乎只想观察一次该值,所以我会改用它:

func getPagesList(completionHandler: @escaping (_ pages: [Page]?, _ error: NSError?) -> Void) {

    func displayError(error: String) {
        print(error)
        completionHandler(nil, self.getErrorFromString(error))
    }

    pagesRef.observeSingleEvent(of: .value, with: { (pagesSnapshot) in
      var pagesList = [Page]()

      for pageSnapshot in pagesSnapshot.children {
          pagesList.append(Page(snapshot: pageSnapshot as! DataSnapshot))
      }

      completionHandler(pagesList, nil)

      }) { (error) in
        // Display error
    }
}

【讨论】:

  • 不,我实际上想让我的 UI 保持最新...问题是我必须多次调用 getPages 函数。这导致存在多个观察者并且完成处理程序被多次调用
  • 你是在多个控制器中调用这个函数吗?因为可以在 viewWillAppear 中创建观察者,在 viewWillDisappear() 中创建 ref.removeAllObservers()
猜你喜欢
  • 1970-01-01
  • 2017-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多