将项目从firebase加载到pickerview时发生问题

时间:2017-03-31 02:54:27

标签: swift firebase firebase-realtime-database

我已经成功创建了一个QuestionModel类,它从firebase中检索项目,如问题,答案字符串和正确的问题。然而,我现在在让这些项目从另一个班级进入选择器视图方面遇到困难。名为QuestionsViewController的类是我在使用问题类从中检索数据方面遇到问题的地方。 QuestionModel类包含从firebase检索数据。我在QuestionsViewController类的代码中遇到了错误的执行错误。这主要发生在尝试在pickverview之前设置itemlabel文本和pickerview函数的代码时。

import Foundation
import Firebase
import FirebaseDatabase
import FirebaseAuth
import CoreData

class QuestionList
{
//properties
public static var Username: String = ""
private static var quiz = [Question]()

static func getDummyQuestions()->[Question]
{
    //create some dummy data for the model
    var ref: FIRDatabaseReference!
    var refHandle: UInt!
    ref = FIRDatabase.database().reference() //reference

    refHandle = ref.child("Questions").child("Q1").observe(.value,       with: { (snapshot)in
        if let dataDict = snapshot.value as? [String: Any] {

            if let quest = dataDict["Question"] as? String,
                let Answers = dataDict["Answers"] as? [String],
                let Correct = dataDict["Correct"] as? Int {
                quiz.append(Question(q: quest, a: Answers, c: Correct))
            }
            print (dataDict)
        }
    })
    return quiz
  } 
}


class Question {
  var quest:String
  var answers:[String]
  var correct:Int

  init(q: String, a:[String], c:Int)
  {
      quest = q
      answers = a
      correct = c
  }

  func isCorrectQuestion(itemSelected: String)->Bool {
      if (itemSelected == answers[correct]) {
          return true
      } else {
          return false
      }
  }
}

import UIKit
import Firebase
import FirebaseAuth

class QuestionsViewController: UIViewController, UIPickerViewDelegate {

@IBOutlet weak var usernamelabel: UILabel! //sets username label
@IBOutlet weak var Next: UIButton! //next button
@IBOutlet weak var itemLabel: UILabel! //item user has selected
@IBOutlet weak var Question: UILabel! //sets question label
@IBOutlet weak var pickerview: UIPickerView! //sets picker view

public var totalQuestions: Int = 0 //sets total question to 0
public var currentQuestion = 0  //sets current question to 0
public var totalCorrect: Int = 0 //sets totalcorrect to 0
var itemSelected: String = "" //item selected
var LabelText = String()
let Exam = QuestionList() //uses the questions class for instances
var Questions = QuestionList.getDummyQuestions()

var ref: FIRDatabaseReference!
var refHandle: UInt!

override func viewDidLoad() {
    super.viewDidLoad() //when the app is loaded

    ref = FIRDatabase.database().reference() //reference
    refHandle = ref.child("Questions").observe(.value, with: { (snapshot)in
        let dataDict = snapshot.value as! [String: AnyObject]
        print (dataDict)
    })
     usernamelabel.text = LabelText //username

    pickerview.delegate = self

    itemLabel.text = "" //loads the item label of whats selected
    itemSelected = QuestionList.getDummyQuestions()[currentQuestion].answers[0] //initially when loaded first item is selected
    Question.text = QuestionList.getDummyQuestions()[currentQuestion].quest
}

func numberOfComponents(in pickerView: UIPickerView) -> Int {
    return 1 //return one component from the picker
}

func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int{
    return QuestionList.getDummyQuestions()[currentQuestion].answers.count  
}

func pickerView(_ pickerView: UIPickerView, titleForRow row: Int,    forComponent component: Int) -> String?{
    return QuestionList.getDummyQuestions().  [currentQuestion].answers[row]
}

func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int){

    itemSelected = QuestionList.getDummyQuestions(). [currentQuestion].answers[row]
}

@IBAction func NextAction(_ sender: Any){

   currentQuestion = currentQuestion + 1 //moves onto next question and   increments

    if (QuestionList.getDummyQuestions()[currentQuestion].isCorrectQuestion(itemSelected: itemSelected)) {
        totalCorrect += 1
        itemLabel.text = String(totalCorrect) + "/" + String(totalQuestions)
    }

    if(currentQuestion < QuestionList.getDummyQuestions().count) {
        pickerview.reloadAllComponents()
        itemSelected = QuestionList.getDummyQuestions()[currentQuestion].answers[1]
        Question.text = QuestionList.getDummyQuestions() [currentQuestion].quest
    } else {
        pickerview.isHidden = true
        Question.text = "You have finished"
        Next.isHidden = true
    }
}

}

1 个答案:

答案 0 :(得分:1)

Firebase函数不会(也不应该)返回值,因为它们是异步的。

因此,返回测验行大多数时间都会失败,因为它会在Firebase有时间从服务器检索数据之前尝试返回数据。

使用Firebase进行编码时,数据仅在函数后面的闭包内有效。所以,例如,这不做什么:

func someFunc() {
    ref.child("Questions").child("Q1").observe(.value, with: { snapshot in
      print(snap)
    })

    print(snap) //this will not print the snap as this line executes *before* the closure
}

这样做是正确的;从Firebase检索数据,填充数组并在闭包内刷新tableview。

static func populateArrayAndRefreshTableView()
{
    var ref: FIRDatabaseReference!= FIRDatabase.database().reference()
    let questionsRef = ref.child("Questions")

    questionsRef.child("Q1").observeSingleEvent(of: .value, with: { snapshot in
        if let dataDict = snapshot.value as? [String: Any] {
            let quest = dataDict["Question"] as? String,
            let Answers = dataDict["Answers"] as? [String],
            let Correct = dataDict["Correct"] as? Int {
            self.quizArray.append(Question(q: quest, a: Answers, c: Correct))
            self.tableView.reloadData()
        }
    })
  } 
}

另请注意,原始代码使用了observe(.value)。这将使观察者附加到ref,如果问题发生变化,将调用代码。它看起来不应该是行为,因此使用observeSingleEvent将调用它一次而不添加观察者。

最后 - 您可能需要重新考虑如何在结构中命名节点。通常最佳做法是将节点名称密钥与它们包含的数据解除关联。

questions
   -UYiuokoksokda
      question: "What significant contribution to bioengineering was made on the Loonkerian outpost on Klendth?"
      correct_answer: answer_1
      answers:
        answer_0: "Left handed smoke shifter"
        answer_1: "The universal atmospheric element compensator"
        answer_2: "Warp coil nullification amplifier"
        answer_3: "H.A.L. 9000"
   -YY8jioijasdjd
      question: "What is Kiri-kin-tha's first law of metaphysics?"
      correct_answer: answer_2
      answers:
        answer_0: "No matter where you go, there you are"
        answer_1: "Only people with sunroofs use them"
        answer_2: "Nothing unreal exists"
        answer_3: "Gravity is heavy"

密钥UYiuokoksokda是使用childByAutoId()创建的。

如果您需要查询答案,您可能希望将它们归一化到自己的节点中,并使用问题密钥作为答案的节点键,或者使用问题密钥保留子节点。