2016-07-23 211 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幫我解決這個問題。