2016-07-23 17 views
0

Firebaseを使用して質問のリストを表形式で表示するアプリケーションを構築しています。ユーザーが質問(テーブルビューのセル)をタップすると、その質問に関連付けられたAnswersのリストを表示する別のView Controllerに接続します。Firebase iOS Swift - チャットの会話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を使用して質問に関連付けられたAnswersを取得する必要があると仮定しています。例: "question01"は、2つのAnswersを持つ最初のQuestionの会話IDです。

各質問に関連付けられた回答データを取得して、後でこれらの回答をテーブルビューで表示できるようにするにはどうすればよいですか?

私はテーブルビューにデータを表示する方法を質問するのではなく、質問の会話IDに関連付けられたFirebaseデータベースから回答データを取得するコードは何かを尋ねています。

+0

一度にすべての回答をしたい、または一度に特定の質問に対応する回答をしますか? – triandicAnt

+0

いくつかの事があります。 1)おそらくremoveObserverWithHandleは必要ありません。限られた数の質問があるようですので、* observeSingleEventOfType(.Value)*を使用してそれらを読み込み、スナップショットを繰り返してテーブルに追加することをお勧めします(新しい質問の通知を希望しない限り、 2)各質問にはキー:値のペアがあり、キーは質問の名前、つまり「question01」です。ユーザーがその質問をタップすると、answer/question01で* observeSingleEventOfType *とほぼ同じコードを使用して、answerViewに回答を入力します。 – Jay

+0

@ triple.s回答は一度に特定の質問に対応したいと思います。たとえば、ユーザーが 'question01'をタップした場合、私は上記のJSONツリーを外しています:「あなたはどう?」アプリケーションは、 "私は偉大なやっている"と "決して良くなった"という2つの質問と回答を持つテーブルビューを表示する新しいビューコントローラに繋がるだろう – alexisSchreier

答えて

0

この質問に答える方法はいくつかあります。

我々は最初のビューコントローラでの質問のテーブルビューを持っており、データソースは質問への参照が含まれていることを考える:question01、question02など

をFirebase構造に基づいて、ユーザーが最初の質問をタップしたときに( question01)、ノード名が2番目のView Controllerに渡されます。コントローラ内のvarに代入するか、segueを介して渡すか、または表現されたオブジェクトで設定することもできます。

どのような場合でも、2番目のビューコントローラはどの質問ノードが(たとえば質問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 
+0

詳細な応答をありがとう!私はあなたを無視していない、私はちょうどあなたのコードをテストしていると私は前進することを妨げているいくつかの別の実行の問題にぶつかった。あなたの答えが私のためにどのように働いたかをあなたに伝えておきます! – alexisSchreier

+0

ありがとうございました@Jay!以下の詳細な回答をご覧ください。 – alexisSchreier

+0

どのように私はこの同じ問題を解決するだろうが、すべての情報を一度にモデルに渡すか?私はこの問題の同じ構造を持っていると仮定します。 –

0

フォローアップされて、私は2番目のテーブルに移入するFirebase回答を得ることができました長い闘いの後に見る。

  1. AnswersViewControllerquestionRefという名前のプロパティへのタップのユーザーという質問(セル)に関連したFirebase JSONノード名(questionSnapshot.key)を渡します。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. 設定データベース2番目のAnswersテーブルビューにデータをロードします(observeSingleEventOfType: withBlock:の代わりにobserveEventType: 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

それは私のために働いた。これがあなたのFirebaseプロジェクトに役立つかどうか教えてください!もう一度、私にこれを解決するのを手伝ってくれてありがとうございます。

関連する問題