Два наблюдателя в одном приложении мешают друг другу - PullRequest
0 голосов
/ 03 июля 2018

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

Моя база данных выглядит так:

"events" : {
    "Oo75nbcDsUK7vPWGDbnL" : {
      "queue" : {
          "K7THdbKzd2aSfaD9a0xmsszkReq1" : {
            "queuePosition" : 1
          },
          "R5UwSxlH3vhH6SjTNMGfMoiaGae2" : {
            "queuePosition" : 2
          }
       }
    }
}

У меня есть класс, который обрабатывает создание наблюдателя для базы данных в реальном времени со следующей статической функцией:

static func listenToRtdbDocument<T: JSONDecodable>(_ refString: String, eventType: DataEventType = .value, orderedByChild: String? = nil, limit: Int? = nil, fromCollection collection: Firebase.RtdbCollections? = nil, completion: @escaping (_ decodedDoc: T?, _ error: Error?) -> ()) -> DatabaseHandle {
    var query: DatabaseQuery
    if let orderedByChild = orderedByChild {
        query = rtdb.child(refString).queryOrdered(byChild: orderedByChild)
    } else {
        query = rtdb.child(refString)
    }

    if let limit = limit {
        query.queryLimited(toFirst: UInt(limit))
    }

    return query.observe(eventType, with: { snapshot in
        guard var docData = snapshot.value as? [String : Any] else {
            completion(nil, nil)
            return
        }
        docData["id"] = snapshot.key
        let decodedDoc = T(json: docData)
        completion(decodedDoc, nil)
    }) { error in
        completion(nil, error)
    }
}

Создает наблюдателя, а затем возвращает ссылку DatabaseHandle. Я использую эту функцию в двух разных местах в моем приложении. Первый находится внутри модели ячейки представления коллекции. Это вызывает функцию так:

queuerRefString = "events/Oo75nbcDsUK7vPWGDbnL/queue/R5UwSxlH3vhH6SjTNMGfMoiaGae2"

func listenToQueuer(updateHandler: @escaping (QueuerJSONModel?) -> ()) {
    guard queuerListener == nil,
        let refString = queuerRefString else { return }

    queuerListener = FirebaseClient.listenToRtdbDocument(refString) { (queuer: QueuerJSONModel?, error) in
        guard error == nil else {
            return
        }
        updateHandler(queuer)
    }
}

Второй от модели контроллера представления. Этот контроллер представления представлен в ячейке представления коллекции:

queueRefString = "events/Oo75nbcDsUK7vPWGDbnL/queue"


func listenToQueue() {
    guard queueChildAddedListener == nil
        let refString = queueRefString else { return }

    queueChildAddedListener = FirebaseClient.listenToRtdbDocument(refString, eventType: .childAdded, orderedByChild: "queuePosition", limit: 25) { [weak self] (queuer: QueuerJSONModel?, error) in
        guard let strongSelf = self,
            let queuer = queuer,
            error == nil else {
                print("an error occurred")
            return
        }
        strongSelf.queuers?.append(queuer)
    }
}

Для наблюдателя упорядоченного массива это всегда возвращает текущего пользователя, а затем оставшуюся часть упорядоченной очереди. Например. Если текущий пользователь находится в позиции 5, массив queuers будет выглядеть так:

5, 1, 2, 3, 4, 6, 7, 8, 9, 10

Как я могу помешать им мешать друг другу ??

UPDATE

Как воспроизвести:

Поместите этот код в метод viewDidLoad контроллера одного представления:

let test1 = Database.database().reference()
        .child("events/Oo75nbcDsUK7vPWGDbnL/queue/R5UwSxlH3vhH6SjTNMGfMoiaGae2")
        .observe(.value, with: { snapshot in
            guard var docData = snapshot.value as? [String : Any] else {
                return
            }
            docData["id"] = snapshot.key
            let queuer = QueuerJSONModel(json: docData)!
            print("ok we got", queuer.queuePosition) // Prints out 2
        })

Затем поместите этот код в метод viewDidLoad контроллера другого представления:

let test2 = Database.database().reference()
        .child("events/Oo75nbcDsUK7vPWGDbnL/queue")
        .queryOrdered(byChild: "queuePosition")
        .queryLimited(toFirst: 25)
        .observe(.childAdded, with: { snapshot in
            guard var docData = snapshot.value as? [String : Any] else {
                return
            }
            docData["id"] = snapshot.key
            let queuer = QueuerJSONModel(json: docData)!
            print("ok we got", queuer.queuePosition) // Prints out 2, then 1
        })

Сначала просмотрите контроллер вида с test1, затем просмотрите тот, у которого test2. Я использую контроллер панели вкладок для переключения между ними.

Как ни странно, если эти два фрагмента кода помещены в один и тот же viewDidLoad метод контроллера представления, тогда упорядоченный слушатель работает как ожидалось.

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

Ответ службы поддержки Firebase на мой вопрос:

По-видимому, это предполагаемое поведение. Идея childAdded заключается в том, что здесь вы нашли и что еще не было добавлено. Таким образом, childAdded дает R5UwSxlH3vhH6SjTNMGfMoiaGae2 в качестве предварительно загруженных данных и возвращает K7THdbKzd2aSfaD9a0xmsszkReq1 в качестве новых данных.

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

0 голосов
/ 04 июля 2018

Наблюдаемое вами поведение связано с тем, что события 'value' отличаются от событий 'childAdded'.

В вашем первом наблюдателе (используя .value) вы просто запрашиваете все данные у events/Oo75nbcDsUK7vPWGDbnL/queue/R5UwSxlH3vhH6SjTNMGfMoiaGae2 в одном снимке. Если какие-либо данные под местоположением изменятся, когда этот наблюдатель все еще будет добавлен, ваш наблюдатель снова будет вызван со снимком всего в этом месте.

В вашем втором наблюдателе (используя .childAdded) вы просите, чтобы ваш наблюдатель был вызван один раз для каждого ребенка в events/Oo75nbcDsUK7vPWGDbnL/queue. Если у вас там двое детей, ваш наблюдатель будет вызван один раз для каждого ребенка. Когда в этом месте будут добавлены новые дети, ваш наблюдатель будет вызываться снова, один раз для каждого нового.

Наблюдатели не мешают друг другу. Они просто делают разные вещи.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...