从firebase检索到swift 3中的多个按钮

Posted

技术标签:

【中文标题】从firebase检索到swift 3中的多个按钮【英文标题】:Retrieve from firebase to multiple buttons in swift 3 【发布时间】:2017-03-16 18:07:15 【问题描述】:

我正在尝试从 firebase 检索数据并显示到多个按钮和标签中。 检索后,我将其保存到字典中。 这是我的模型

import Foundation
import Firebase

    class QuestionModel: NSObject 

        var CorrectAnswer: String!
        var Question: String!
        var optionA: String!
        var optionB: String!
        var optionC: String!

        init(snapshot: FIRDataSnapshot) 
            if let snapshotDict = snapshot.value as? Dictionary<String, Any> 
                CorrectAnswer = snapshotDict["CorrectAnswer"] as? String
                Question = snapshotDict["Question"] as? String
                optionA = snapshotDict["optionA"] as? String
                optionB = snapshotDict["optionB"] as? String
                optionC = snapshotDict["optionC"] as? String
            
        
    

我的 JSON

我尝试了一些方法,但它返回我 nil 。我认为因为异步 firebase。

这是我的代码。

import Foundation
import UIKit
import Firebase
import FirebaseDatabase

class AnsweringQuestionViewController: UIViewController 

    @IBOutlet weak var qLabel: UILabel!
    @IBOutlet weak var buttonA: UIButton!
    @IBOutlet weak var buttonB: UIButton!
    @IBOutlet weak var buttonC: UIButton!
    @IBOutlet weak var correctAnswer: UIButton!

    //var buttons: [UIButton]! thinking of using button tags?

    var ref: FIRDatabaseReference!
    var questionModel : [QuestionModel] = []

    override func viewDidLoad()
        super.viewDidLoad()
      //  FIRDatabase.database().persistenceEnabled = true
        ref = FIRDatabase.database().reference()
        db()
    
    func db()
        ref.child("Science").observe(.value, with: 
            snapshot in
            for child in snapshot.children 
                let user = QuestionModel.init(snapshot: (child as? FIRDataSnapshot)!)
                self.questionModel.append(user)
            
         self.qLabel.text = self.questionModel[0].Question
        self.buttonA.setTitle("\(self.questionModel[0].CorrectAnswer)", for: UIControlState.normal)
        , withCancel: nil)
        

请使用我仍在学习的代码。我不知道从这里到哪里去将我的数据显示到多个按钮中并确定哪个按钮被“点击”是正确的答案。

如果你愿意的话,如果你能以更简洁的方式重构我的代码,我会非常高兴。谢谢你:)

【问题讨论】:

【参考方案1】:

试试这个……

import FirebaseDatabase

class Question 

   var correctAnswer: String?
   var question: String?
   var optionA: String?
   var optionB: String?
   var optionC: String?

   init(snapshot: FIRDataSnapshot)
       if let snap = snapshot.value as? [String: String] 
           correctAnswer = snap["CorrectAnswer"]
           question = snap["Question"]
           optionA = snap["OptionA"]
           optionB = snap["OptionB"]
           optionC = snap["OptionC"]
       
   






import FirebaseDatabase
import UIKit

class ViewController: UIViewController 

   @IBOutlet weak var qLabel: UILabel!
   @IBOutlet weak var buttonA: UIButton!
   @IBOutlet weak var buttonB: UIButton!
   @IBOutlet weak var buttonC: UIButton!
   @IBOutlet weak var correctAnswer: UIButton!

   var fireRootRef: FIRDatabaseReference!
   var questions = [Question]()

   override func viewDidLoad() 
       super.viewDidLoad()
       fireRootRef = FIRDatabase.database().reference()
       fetchQuestions(inCategory: "Science")
   


   func fetchQuestions(inCategory category: String)
       let questionsRef = fireRootRef.child(category)

       questionsRef.observe(.value, with: (snapshot)-> Void in

           var allQuestions = [Question]()
           for child in snapshot.children 
               allQuestions.append(Question(snapshot: child as! FIRDataSnapshot))
           
           self.questions = allQuestions
           self.reloadUI(withQuestions: self.questions)
       )
   

   func reloadUI(withQuestions questions: [Question])
       guard questions.count > 0 else return

        if let answerToQuestion1 = questions[0].correctAnswer, let wrongAnswer = questions[0].optionA, let wrongAnswer2 = questions[0].optionB, let wrongAnswer3 = questions[0].optionC 

            let randomOrderedAnswers = [answerToQuestion1, wrongAnswer, wrongAnswer2, wrongAnswer3].shuffled()

            buttonA.setTitle(randomOrderedAnswers[0], for: .normal)
            buttonB.setTitle(randomOrderedAnswers[1], for: .normal)
            buttonC.setTitle(randomOrderedAnswers[2], for: .normal)
            correctAnswer.setTitle(randomOrderedAnswers[3], for: .normal)//keep in mind the correctAnswer label wont always contain the actual correct answer now

         else 
            print("failed to get value for one of the answes options")
        

       if let questionText = questions[0].question 
           qLabel.text = questionText
        else 
           qLabel.text = "failed to get question text"
       
   






    extension MutableCollection where Indices.Iterator.Element == Index 
/// Shuffles the contents of this collection.
    mutating func shuffle() 
        let c = count
        guard c > 1 else  return 

        for (firstUnshuffled , unshuffledCount) in zip(indices, stride(from: c, to: 1, by: -1)) 
            let d: IndexDistance = numericCast(arc4random_uniform(numericCast(unshuffledCount)))
            guard d != 0 else  continue 
            let i = index(firstUnshuffled, offsetBy: d)
            swap(&self[firstUnshuffled], &self[i])
        
    


extension Sequence 
    /// Returns an array with the contents of this sequence, shuffled.
    func shuffled() -> [Iterator.Element] 
        var result = Array(self)
        result.shuffle()
        return result
    

更新 我添加了扩展,允许您打乱数组中元素的顺序,以便您可以“随机”设置答案标签,并且正确的答案不会总是在同一个地方。该扩展由@NateCook 提供,来自this question here

要知道是否选择了正确答案,只需检查所选按钮的文本是否 == 到问题的正确答案属性,例如 if buttonA.title(for: .normal)! == questions[0].correctAnswer print("correct answer selected)" 。只需确保解开 buttonA.title(for: .normal) 的可选值,否则它前面会有“可选”一词,因此不会完全等于正确答案文本

【讨论】:

是的,它可以在按钮中显示。现在我的问题是所有正确答案总是在正确答案按钮中。但我会借此机会问这个问题,我怎样才能将它显示为随机按钮并知道单击的按钮是否是正确的答案(打印语句对我来说就足够了)。 查看我的更新答案,您可以接受这是正确答案 发自内心。谢谢!你帮了我很多。是的,现在可以了:)。谢谢你的最后一段,它帮助我大致了解我接下来要做什么。再次感谢你:) 我有一个后续问题。鉴于我有 IBaction func next(),我如何从问题 1 转到问题 2? 不客气!这是一个非常广泛的问题,有很多方法可以做到这一点,我强烈建议您自己尝试一下,如果您遇到问题,请将您尝试过的代码发布到一个新问题中。但是,这是我对如何做到这一点的想法...在next() 函数中,获取从检索到的firebase 值设置的questions 数组中的下一个元素,然后重新加载所有UI 标签/按钮标题新问题对象中的属性。因此,当使用水龙头“下一步”。您执行 setupNextQuestion() ,它从问题数组中获取下一个问题对象并重置所有标签

以上是关于从firebase检索到swift 3中的多个按钮的主要内容,如果未能解决你的问题,请参考以下文章

使用swift 3如何从firebase中检索另一个数据中的数据[关闭]

Swift - 如何从 Firebase 检索多个值并将它们显示在 UITABLEVIEW

如何使用 Swift 中的 url 从 firebase 正确检索数据?

如何从firebase检索多个数据到android中的列表视图?

从 Firebase 检索和读取数据作为 NSArray (Swift 3)

从 Firebase Auto Id 中检索数据 - Firebase Swift