Firebase: когда вызывать removeObserverWithHandle в swift

Документация говорит, что вам нужно позвонить observeEventType:withBlock удалить наблюдателя, если он вам больше не нужен.

Я видел образцы, где это называется в ViewDidDisAppear, Я также нахожу некоторый код Obj-C под названием этот метод в deinit, что не является необходимым в Swift.

Однако в моем простом приложении я хочу, чтобы данные синхронизировались, пока я в приложении. Если это так, я должен позвонить observeEventType:withBlock Когда-либо?

Я проверил пример кода Chat-Swift на сайте Firebase и не нашел observeEventType:withBlock,

Значит, нормально не звонить observeEventType:withBlock:. если я хочу, чтобы наблюдатель был включен, когда приложение используется?

Спасибо.

ОБНОВИТЬ

Спасибо Джею и Дэвиду. Я вижу, что имеет смысл наблюдать в ViewWillAppear и удалять его в ViewDidDisappear.

Тем не менее, я использую Наблюдение за событием для отслеживания любых изменений значения для узла и будет обновлять пользовательский интерфейс, если таковые имеются. Если я положу его в ViewWillAppear:

 override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    ref.observeEventType(.Value, withBlock: { snap in {
      // **update UI if there is any Value change** 
    })
  }

Проблема с этим viewWillAppear является то, что он вызывается каждый раз, когда появляется представление, независимо от того, изменяется значение или нет. Из-за этого снимок загружается, и мой пользовательский интерфейс обновляется каждый раз, когда я возвращаюсь к представлению. Это становится контрпродуктивным.

Я также пытался ChildAdded/ChildRemovedоднако он возвращает только последний узел, а не путь из моей ссылки:

Например, если я добавлю к ref/child1/child2/child3/value, ChildAdded вернул бы только child3/value.

Так что, если мне нужно соблюдать ценность, кажется, что ViewDidLoad лучше? Таким образом, он получает снимок один раз при загрузке представления и будет повторяться всякий раз, когда есть изменение, но не получит снимок только потому, что представление появляется.

3 ответа

Чтобы развить превосходный ответ @Jay:

В UIViewControllerсоздать ссылку как свойство. Инициализировать ссылку в viewDidLoad, Наблюдайте за событиями в viewWillAppear, Удалить наблюдателей в viewDidDisappear,

class MyViewController: UIViewController {

  var ref: Firebase!

  // Called only on load, great place to initialize
  override func viewDidLoad() {
    super.viewDidLoad()
    ref = Firebase(url: "https://<YOUR-FIREBASE-APP>.firebaseio.com/updates")
  }

  // Can be called many times to go on screen
  // Syncing should only occur when on view to conserve memory
  override func viewWillAppear(animated: Bool) {
    super.viewWillAppear(animated)

    ref.observeEventType(.Value, withBlock: { snap in {
      // do something with the data 
    })
  }

  // Can be called many times to off screen
  // Remove observers on the ref to conserve memory
  override func viewDidDisappear(animated: Bool) {
    super.viewDidDisappear(animated)
    ref.removeAllObservers() 
  }

}

Согласно вашему редактированию:

The problem with putting it in viewWillAppear is that, it gets called every time the view appears, regardless of Value change or not. Because of this, the snapshot is downloaded and my UI gets refreshed every time I return to the view. This becomes counterproductive.

Firebase построен для скорости. Это те вещи, которые вы оставляете на усмотрение клиента, потому что он имеет несколько функций, которые справляются с этими ситуациями.

Клиент Firebase имеет встроенное кэширование. Если вы не загружаете мегабайт данных в viewDidAppear обновление является номинальным. Когда наблюдатель стреляет viewDidAppear это не обязательно означает, что он загружает данные снова. viewDidAppear функция, где ваши наблюдатели принадлежат.

К вашему сведению, я сотрудник Firebase, работающий на iOS.

Наблюдение за событием: тип withBlock используется для наблюдения за узлом.

Как только приложение наблюдает за узлом, оно будет продолжать наблюдать, если только вы не выйдете из приложения или не скажете Firebase прекратить наблюдение.

Чтобы прекратить наблюдение, вы можете использовать дескриптор, который был возвращен, когда вы начали наблюдать так:

    //start observing and get a handle
FirebaseHandle handle = [ref observeEventType:FEventTypeValue withBlock:^(FDatasnapshot* snapshot) {
        // do some stuff with the snapshot data
    }];

    [ref removeObserverWithHandle:handle]; //stop observing using the handle

или как это

[ref removeAllObservers];

Наблюдение и остановка наблюдения в viewWillAppear() и viewWillDisappear() будут работать, но это вызывает добавление дочерних значений (в случае использования.added/.value для типа наблюдения) снова, когда появляется контроллер представления.

Я предпочитаю установить наблюдение в viewDidLoad() и прекратить наблюдение в deinit.

Некоторые говорят, что deinit не вызывается после установки наблюдения, но причина в том, что когда вы устанавливаете наблюдение, закрытие наблюдателя сильно удерживает себя, так что deinit никогда не будет вызываться. Вы можете установить слабый или неподходящий внутри закрытия.

Вот пример.

class SomeViewController : UIViewController {

  override func viewDidLoad() {
    super.viewDidLoad()

    someRef.observe(.childAdded) { [weak self] (snapshot) in
      guard let weakSelf = self else { return }
      ...
    }
  }

  deinit {
    print("deinit called")
    someRef.removeAllObservers()
  }

}

Пожалуйста, не забудьте написать [слабое Я], иначе deinit никогда не будет вызван. Надеюсь, поможет.

Другие вопросы по тегам