Firebase iOS Swift - 检索与聊天对话ID

时间:2016-07-23 00:39:12

标签: ios swift firebase firebase-realtime-database

我正在使用Firebase构建应用,该应用在表格视图中显示问题列表。当用户点击问题(表格视图中的一个单元格)时,该应用程序会切换到另一个视图控制器,该控制器显示与该问题相关联的答案列表。

这就是我构建数据库的JSON树的方式:

{
 "answers": {
     "question01": {
         "answer01": {
             "name": "kelly"
             "text": "I'm doing great"
         },
         "answer02": {
             "name": "george"
             "text": "never been better"
         }
     }
 },

 "questions": {
     "question01": {
             "name": "courtney"
             "text": "how are you?"
     },
     "question02": {
             "name": "bob"
             "text": "why is the earth round?"
     }
  }

我能够在第一个表格视图中显示问题,以下代码没有问题:

    // MARK: - Firebase Database Configuration
    func configureDatabase() {//this method gets called in viewDidLoad

        ref = FIRDatabase.database().reference()

        //listen for new questions in the database
        _refHandle = self.ref.child("questions").observeEventType(.ChildAdded, withBlock: {(snapshot) -> Void in

            self.questionsArray.append(snapshot)
            self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: self.questionsArray.count-1, inSection: 0)], withRowAnimation: .Automatic)
        })
    }

    deinit {

        self.ref.child("questions").removeObserverWithHandle(_refHandle)
    }


// MARK: - UITableViewDataSource & UITableViewDelegate methods
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return questionsArray.count
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell: UITableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("tableViewCell", forIndexPath: indexPath)

        //unpack question from database
        let questionSnapshot: FIRDataSnapshot! = self.questionsArray[indexPath.row]
        let question = questionSnapshot.value as! Dictionary<String, String>
        let name = question[Constants.QuestionFields.name] as String!
        let text = question[Constants.QuestionFields.text] as String!

        cell!.textLabel?.text = name + ": " + text
        cell!.imageView?.image = UIImage(named: "ic_account_circle")
        if let photoUrl = question[Constants.QuestionFields.photoUrl], url = NSURL(string:photoUrl), data = NSData(contentsOfURL: url) {
        cell!.imageView?.image = UIImage(data: data)
        }

        return cell!
    }

Firebase's guide to structuring data之后,我假设我需要使用JSON树中每个子项共有的对话ID来检索与问题相关联的答案。例如:“question01”将是第一个有两个答案的问题的对话ID。

如何检索与每个问题相关的答案数据,以便我以后可以在表格视图中显示这些答案?

为了清楚起见,我不是问如何在表格视图中显示数据,而是从我的Firebase数据库中检索与问题对话ID相关联的答案数据的代码是什么。

2 个答案:

答案 0 :(得分:0)

有很多方法可以回答这个问题。

鉴于我们在第一个视图控制器中有一个问题的tableview,数据源包含对问题的引用:question01,question02等。

基于Firebase结构,当用户点击第一个问题(question01)时,节点名称将传递给第二个视图控制器。它可以分配给控制器中的var或通过segue传递,甚至可以用表示的对象设置。

在任何情况下,第二个视图控制器都会知道什么是问题节点(例如,问题01),然后从viewDidLoad加载Firebase中的数据并更新tableView就很简单了。

var questionRef: String() //this will contain question01 for example

override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view.
    loadFromFirebase()
}

然后

func loadFromFirebase {

     let ref = answersRef.child(questionRef) //will be answers/question01
     ref.observeSingleEventOfType(.Value, withBlock: { snapshot in

          for child in snapshot.children {

            let key = child.key as String
            let text = child.value["text"] as! String
            print("answer: \(key)  text: \(text)")
            //add data to a tableViewDataSource
          }
          //reload the tableview
      })
}

,其输出是

answer: answer01  text: I'm doing great
answer: answer02  text: never been better

答案 1 :(得分:0)

继续上面@ Jay的回答,经过长时间的努力,我能够让Firebase Answers在第二个表视图中填充。

  1. 将与用户点击的问题(单元格)相关联的Firebase JSON节点名称(questionSnapshot.key)传递到questionRef中名为AnswersViewController的属性中

    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        if segue.identifier == Constants.Segues.HomeToAnswersNavController {
            guard let selectedIndexPath = self.tableView.indexPathForSelectedRow else { return }
            let questionSnapShot: FIRDataSnapshot! = self.questionsArray[selectedIndexPath.row]
            let selectedQuestion = questionSnapShot.key
    
            guard let destinationVC = segue.destinationViewController as? AnswersViewController else { return }
            destinationVC.questionRef = selectedQuestion
        }
    }
    
    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        performSegueWithIdentifier(Constants.Segues.HomeToAnswersNavController, sender: self)
    }    
    
  2. 在AnswersViewController中配置数据库并在第二个Answers表视图中加载数据(我选择使用observeEventType: withBlock而不是observeSingleEventOfType: withBlock:,因为我希望收到有关添加新问题和答案的通知到数据库):

    override func viewDidLoad() {
    super.viewDidLoad()
    self.ref = FIRDatabase.database().reference()
    self.tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "tableViewCell")
    self.configureDatabase()
    }
    
    deinit {
    self.ref.child("answers").child(questionRef!).removeObserverWithHandle(_refHandle)
    }
    
    func configureDatabase() {
    self.ref = FIRDatabase.database().reference()
    _refHandle = self.ref.child("answers").child(questionRef!).observeEventType(.ChildAdded, withBlock: { (snapshot) -> Void in
        self.answersArray.append(snapshot)
        self.tableView.insertRowsAtIndexPaths([NSIndexPath(forRow: self.answersArray.count-1, inSection: 0)], withRowAnimation: .Automatic)
    })
    }
    
    
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.answersArray.count
    }
    
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell: UITableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("tableViewCell", forIndexPath: indexPath)
    //unpack question from database
    let answerSnapshot: FIRDataSnapshot! = self.answersArray[indexPath.row]
    let answer = answerSnapshot.value as! Dictionary<String, String>
    let name = answer[Constants.AnswerFields.name] as String!
    let text = answer[Constants.AnswerFields.text] as String!
    cell!.textLabel?.text = name + ": " + text
    cell!.imageView?.image = UIImage(named: "ic_account_circle")
    if let photoUrl = answer[Constants.QuestionFields.photoUrl], url = NSURL(string:photoUrl), data = NSData(contentsOfURL: url) {
        cell!.imageView?.image = UIImage(data: data)
    } 
    return cell!
    }
    
  3. 别忘了这最后一步!我花了一大笔时间试图弄清楚为什么我的答案数据不会显示在我的表视图中,因为我忘了在Firebase控制台中发布一组允许读/写权限的数据库规则:

    Screenshot of my Firebase console showing updated Database Rules

  4. 这对我有用。如果这有助于您的Firebase项目,请告知我们!再次感谢@Jay帮助我解决这个问题。