Swift -Firebase - возможно ли одновременно публиковать и наблюдать - PullRequest
0 голосов
/ 12 марта 2020

Когда я хочу observe, я запускаю:

let likesRef = Database.database().reference().child("likes").child(postId)
likesRef.observeSingleEvent(of: .value, with:{ (snapshot) in

    let likes = snapshot.childrenCount

    let totalLikes = Int(likes)

    // display totalLikes
})

Когда я хочу опубликовать, я запускаю:

let dict = [uid: 1]
let likesRef = Database.database().reference().child("likes").child(postId)
likesRef.updateChildValues(dict) { [weak self](error, ref) in
    if let error = error { return }
    // if no error then update the ref 
})

При публикации completionBlock имеет 2 значения:

withCompletionBlock: (Error?, DatabaseReference)

Есть ли способ, которым я также могу observe ссылка, на которую я отправляю сообщение, используя 2-е completionBlock значение: DatabaseReference:

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

let dict = [uid: 1]
let likesRef = Database.database().reference().child("likes").child(postId)
likesRef.updateChildValues(dict) { (error, ref) in

    if let error = error { return }

    // *** somehow get the total amount of likes from the ref *** 

    // If possible I want to avoid this code below
    likesRef.observeSingleEvent(of: .value, with:{ (snapshot) in

        let likes = snapshot.childrenCount

        let totalLikes = Int(likes)

        // display totalLikes
     })
})

Ответы [ 2 ]

1 голос
/ 12 марта 2020

На самом деле невозможно получить оба события одновременно. Как только вы захотите, когда ваши данные попадут в базу данных firebase, вы получите событие Value, Change, ChieldAdded на стороне приложения. Это займет 1-2 секунды или меньше в зависимости от Inte rnet. Итак, сначала позвонит Post, а затем позвонит наблюдатель.

Наблюдатель может получить это двумя способами:

Шаг 1: Добавить слушателя Child Change

let likesRef = Database.database().reference().child("likes").child(postId)
likesRef.observe(.childChanged, with: {
        (snapshot) in

    let likes = snapshot.childrenCount

    let totalLikes = Double(Int(likes))

    // display likes
 })

Child change слушатель прослушивает изменения на снимке

Шаг 2: Установите значение слушателя

let likesRef = Database.database().reference().child("likes").child(postId)
likesRef.observe(.value, with: {
        (snapshot) in

    let likes = snapshot.childrenCount

    let totalLikes = Double(Int(likes))

    // display likes
 })

Значение слушателя слушает каждый раз

Надеюсь, это поможет ...

0 голосов
/ 13 марта 2020

Вот очень сокращенный код для выполнения sh задачи добавления пользователя uid, которому нравится публикация, и увеличения счетчика с помощью runTransactionBlock. Имейте в виду, что есть 100 способов сделать это.

Предлагаемая структура

all_posts
   post_0
      like_count: 2
      post: "Hello, World"

likes
   post_0
      uid_0: true
      uid_1: true

На основе вопроса и обсуждения я разбил посты и лайки на отдельные узлы. Причина в том, что когда сообщения загружены, они, вероятно, будут отображаться в списке, и все, что действительно нужно в этот момент, - это запись topi c и общее количество лайков, поэтому я включил «like_count» в сообщение. узел.

Если бы мы добавили фактические лайки в самом почтовом узле, это может быть 10 000 или 10 000 000, и нет никакой причины загружать все эти данные при загрузке в сообщениях. Наличие такого количества лайков также может привести к перегрузке устройства.

Внутри узла лайков каждый ключ поста ссылается на пост в узле all_posts. Дети - это UID пользователей, которым понравился пост, а значение - логическое «true» в качестве заполнителя. Узлы без значений не могут существовать, поэтому «true» сохраняет их на месте и представляет собой небольшое количество данных.

Тогда код -

func updatePostWithLikesViaTransaction() {
    let postsRef = self.ref.child("all_posts") //self.ref points to my Firebase
    let thisPostRef = postsRef.child("post_0")

    thisPostRef.runTransactionBlock ({ (currentData: MutableData) -> TransactionResult in
        if var data = currentData.value as? [String: Any] {
            var count = data["like_count"] as? Int ?? 0
            count += 1
            data["like_count"] = count
            currentData.value = data
        }

      return TransactionResult.success(withValue: currentData)
    }) { (error, committed, snapshot) in
        if let error = error {
            print(error.localizedDescription)
            return
        }
        print("successfully incremented counter")
        let likesRef = self.ref.child("likes")
        let likesPostRef = likesRef.child(thisPostRef.key!)
        likesPostRef.child("uid_2").setValue(true)
    }
}

Вышеприведенное не является идеальным, но демонстрирует процесс (и работает с представленной структурой).

Сначала мы получаем ссылку на сообщение, которое мы хотим обновить, а затем в блоке транзакции читаем дочерний элемент current_ata 'like_count', который возвращает 2 на основе значения в структуре. Увеличивается до 3, обновляется в currentData, а затем обновляется через TransactionResult.

runTransactionBlock также имеет необязательный обратный вызов завершения, и мы используем его для успешного обновления сообщения в лайках, используя uid и true пользователей. .

Конечным результатом выполнения этого является то, что счетчик увеличивается до 3, а 'uid_2: true' добавляется к узлу «likes / post_0 '

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