为什么在添加新数据时不调用.childAdded?火力基地 [英] Why .childAdded is not called when new data is added? Firebase

查看:35
本文介绍了为什么在添加新数据时不调用.childAdded?火力基地的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在/media节点上更新数据时,我试图从media读取数据,但未调用.observe(.childAdded.
例如,我在/media/-LKN1j_FLQuOvnhEFfao/caption处更新数据,但是我从未在observeNewMedia中收到该事件.
ViewDidLoad第一次完成时,我可以毫无问题地读取数据.

I am trying to read data from media when data is updated on /media node, but .observe(.childAdded is not called.
For example, I update data at /media/-LKN1j_FLQuOvnhEFfao/caption , but I never receive the event in observeNewMedia .
I can read the data with no problem the first time when ViewDidLoad completes.

第一步是下载用户数据,第二步是从currentUser获取 locality ,最后一步是在媒体上附加监听器.childAdded.
我怀疑事件未触发,因为在DDatabaseRReference.users(uid: uid).reference().observe(.value

The first step is to download the user data, second is to get the locality from currentUser and the last step is to attach a listener .childAdded on media.
I suspect that the event is not triggered because fetchMedia is called inside DDatabaseRReference.users(uid: uid).reference().observe(.value

media
  -LKNRdP4ZsE3YrgaLB30
        caption: "santa"
        mediaUID: "-LKNRdP4ZsE3YrgaLB30"
        locality: "barking"

users
  Q6Dm3IMLNLgBH3ny3rv2CMYf47p1
       media
          -LKNReJCxgwtGRU6iJmV: "-LKNRdP4ZsE3YrgaLB30"
       email: "john@gmail.com"
       locality: "barking"


  //enables the programmer to create references to different childs in Firebase
  enum DDatabaseRReference {

   case root
   case users(uid:String)
   case media  //to store photos

    func reference() -> DatabaseReference {
       return rootRef.child(path)
   }


  //return root reference to our database
   private var rootRef: DatabaseReference {
       return Database.database().reference()
  }

private var path: String {

      switch self { //self is the enum DDatabaseReference
       case .root:
         return ""

       case .users(let uid):
         return "users/\(uid)"

       case .media:
          return "media"        
       }
    }

  }//end of enum DatabaseReference




 class NewsfeedTableViewController: UITableViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

            //observe ~/users/uid
    DDatabaseRReference.users(uid: uid).reference().observe(.value, with: { (snapshot) in

        DispatchQueue.main.async {
            if let userDict = snapshot.value as? [String : Any] {
                self.currentUser = UserModel(dictionary: userDict)
                self.fetchMedia()
                self.tableView.reloadData()
            }
        }
    })

  }

    func fetchMedia() {   

 Media.observeNewMedia((currentUser?.locality)!) { (newMedia) in

        //check if newly downloaded media is already in media array
        if !self.media.contains(newMedia) {
            self.media.insert(newMedia, at: 0)
            self.tableView.reloadData()
        }else {
            //remove old media and add the newly updated one
            guard let index = self.media.index(of: newMedia) else {return}
            self.media.remove(at: index)
            self.media.insert(newMedia, at: 0)
            self.tableView.reloadData()
        }
    }
}

 }//end of NewsfeedTableViewController


 class Media {

class func observeNewMedia(_ userLocality: String, _ completion: @escaping (Media) -> Void) {


    DDatabaseRReference.media.reference().queryOrdered(byChild: "locality").queryEqual(toValue: userLocality).observe(.childAdded, with: { snapshot in
        guard snapshot.exists() else {
       print("no snap ")
        return}
        print("snap is \(snapshot)")
        let media = Media(dictionary: snapshot.value as! [String : Any])
        completion(media)
    })
  }
} //end of class Media

推荐答案

让我们首先更新结构,使其更易于查询

Let's first update the structure so make it more queryable

假设一个用户节点

users
   -Q6Dm3IMLNLgBH3ny3rv2CMYf47p1  //this is each users uid
      email: "john@gmail.com"
      locality: "barking"

和一个包含所有用户媒体的媒体节点

and a media node that contains media for all users

media
   -abcdefg12345 //node created with childByAutoId
      caption: "santa"
      for_uid: -Q6Dm3IMLNLgBH3ny3rv2CMYf47p1 //matches the uid in the /users node

然后我们的主viewController包含对Firebase的引用,并将用户登录

Then our main viewController which contains a reference to Firebase and logs the user in

class ViewController: UIViewController {
   var ref: DatabaseReference!

   override func viewDidLoad() {
      super.viewDidLoad()
      self.ref = Database.database().reference()
      //log user in which will populate the Auth.auth.currentUser variable
    }
   .
   .
   .

我们需要一个对象来存储媒体,然后需要一个数组来保存这些对象

We need an object to store the media in and then an array to hold those objects

class MediaClass {
    var key = ""
    var caption = ""

    init(k: String, c: String) {
        self.key = k
        self.caption = c
    }
}

var mediaArray = [MediaClass]()

然后设置观察者,这些观察者将在添加,更改或删除该用户的媒体时添加,更新或从阵列中删除.

then set up the observers which will add, update or remove from the array when media for this user is added, changed or removed.

let thisUid = Auth.auth().currentUser?.uid
let mediaRef = self.ref.child("media")

let queryRef = mediaRef.queryOrdered(byChild: "for_uid").queryEqual(toValue: thisUid)

queryRef.observe(.childAdded, with: { snapshot in
    let dict = snapshot.value as! [String: Any]
    let key = snapshot.key
    let caption = dict["caption"] as! String
    let m = MediaClass.init(k: key, c: caption)
    self.mediaArray.append(m)
    self.tableView.reloadData()
})

queryRef.observe(.childChanged, with: { snapshot in
    let dict = snapshot.value as! [String: Any]
    let key = snapshot.key
    let caption = dict["caption"] as! String
    let index = self.mediaArray.index { $0.key == key } //locate this object in the array
    self.mediaArray[index!].caption = caption //and update it's caption
    self.tableView.reloadData()
})

//leaving this an an exercise
queryRef.observe(.childRemoved....

请注意,我们通过查询向媒体节点添加了.childAdded,.childChanged和.childRemoved事件,因此应用程序将仅接收与此用户有关的事件.

Note we added .childAdded, .childChanged and .childRemoved events to the media node via a query so the only events the app will receive are the ones that pertain to this user.

还请注意,没有错误检查,因此需要添加.

Also note there's no error checking so that needs to be added.

这篇关于为什么在添加新数据时不调用.childAdded?火力基地的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆