swift - 为什么添加新数据时不调用 .childAdded?火力地堡

标签 swift firebase firebase-realtime-database

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

第一步是下载用户数据,第二步是从 currentUser 获取位置,最后一步是在媒体上附加一个监听器 .childAdded。< br/> 我怀疑该事件没有被触发,因为在 DDatabaseRReference.users(uid: uid).reference().observe(.value

中调用了 fetchMedia
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

最佳答案

让我们首先更新结构,使其更具可查询性

假设一个用户节点

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

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

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

然后是我们的主视图 Controller ,它包含对 Firebase 的引用并记录用户

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
    }
   .
   .
   .

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

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

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

var mediaArray = [MediaClass]()

然后设置观察者,当该用户的媒体被添加、更改或删除时,观察者将添加、更新或从数组中删除。

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 事件,因此应用将收到的唯一事件是与该用户相关的事件。

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

关于swift - 为什么添加新数据时不调用 .childAdded?火力地堡,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51934893/

相关文章:

ios - 检查我的 IOS 应用程序是否更新

java - 图像未在 firebase RecyclerView 中显示

swift - #selector 的局部函数

ios - 更改 UILabel 中某个单词的颜色

swift - NSSegmentedControl 分段可选事件虽然禁用

javascript - 比较两个 +new 日期字符串

java - Google App Engine 上的 NoSuchMethod 错误

firebase - 我怎么知道 Firebase 云消息传递 token 已停用?

java - 将 Firebase 字符串数组检索到数组

java - java中无法获取图片url