2016-07-23 210 views
0

我使用的显示在表视图中的问题的列表火力地堡构建应用程序的子数据。当用户点击一个问题(表格视图中的一个单元格)时,该应用程序会跳到另一个视图控制器,该控制器显示与该问题关联的答案列表。火力地堡的iOS斯威夫特 - 检索对应的聊天对话ID

这是我是如何构建我的数据库的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,它有两个答案。

我怎样才能检索到相关的每一个问题,这样我可以在以后显示在表视图这些答案应答数据?

只是要清楚,我不问如何在表视图中显示的数据,而是什么是从相关的一个问题的谈话ID我的火力地堡数据库检索应答数据的代码。

+0

你想要一次回答所有答案吗?或者一次回答相应的问题? – triandicAnt

+0

一些事情。 1)你可能不需要removeObserverWithHandle。它似乎只有有限的几个问题,所以我建议使用* observeSingleEventOfType(.Value)*来读取它们,然后迭代快照以将它们添加到表格中(除非您想要通知新问题,那么它很好)2)每个问题都有一个关键字:值对,关键字是问题的名称,即'question01'。当用户点击该问题时,使用与* answersSingleEventOfType *相同的代码来填充答案tableView。 – Jay

+0

@ triple.s我想每次回答对应于一个特定的问题。例如,如果用户点击了“question01”,那么我就会发布上面提到的JSON树:“你好吗?”那么应用程序会延续到一个新的视图控制器,该视图控制器显示一个表视图,其中包含'question01'的两个答案,即“我做得很好”和“从未更好” – alexisSchreier

回答

0

有多种方式来回答这个问题。

由于我们有一份问题的tableview在第一视图中的控制器和数据源包含了参考问题:基于火力地堡结构中,当用户轻击的第一个问题question01,question02等

( question01)该节点名称被传递给第二个视图控制器。它可以分配给控制器内的一个var,或者通过segue传递,甚至可以用一个表示的对象来设置。

在任何情况下,第二个视图控制器会知道什么问题节点(例如question01),然后从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 
+0

非常感谢您的详细回复!我并没有忽视你,我只是测试你的代码,并且遇到了一些阻碍我前进的单独执行问题。我会告诉你如何你的答案为我工作! – alexisSchreier

+0

得到它的工作,谢谢@杰伊!请参阅下面的详细答案。 – alexisSchreier

+0

我该如何解决这个相同的问题,但一次将所有信息传递给模型?让我们假设我有这个问题的结构。 –

0

上@以上周杰伦的回答之后,我能得到的火力地堡回答第二个表来填充经过漫长的斗争后再看。

  1. 传递火力地堡JSON节点名称(questionSnapshot.key)相关的问题(电池),用户在AnswersViewController拍了拍到一个名为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. 配置数据库并在第二个答案表视图中加载数据(我选择使用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. 不要忘了这最后一步!我花了很多时间的尴尬量试图找出为什么,因为我忘了出版一套在火力地堡控制台数据库规则我应答数据不会在我的表视图中显示允许读/写权限:

    Screenshot of my Firebase console showing updated Database Rules

这对我有用。请让我知道这是否有助于您的Firebase项目!再次,谢谢@Jay帮我解决这个问题。