在ios swift中将firebase数据添加到数组中

时间:2015-07-26 03:00:28

标签: ios arrays swift firebase

我在从firebase数据库获取数据并将其添加到数组时遇到问题。 方法 getNewQuote 的打印输出显示数组为空,但屏幕截图显示标签已在 getNewQuote <中更新/ strong>方法。

怎么会发生这种情况? getNewQuote 方法中的事件是否存在延迟? 此外,如何使用 getNewQuote 方法的第4次迭代更新标签,而不是最后一次迭代。

提前谢谢!

代码细分
循环迭代5次并执行以下操作:
      1.创建一个随机数
      2.将随机数传递给方法 getNewQuote      (此方法从数据库中获取数据并附加到数组 quotesMessages ) 在循环迭代之后,打印完整的数组

代码:

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var message: UILabel!

    var QuoteRef:String = "https://motivatr.firebaseIO.com/quotes"

    var quotesMessages = [String]()

    /* */
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        for (var i = 0; i < 5; i++) {
            var currRandomNumber = self.createRandomNum()
            self.getNewQuote(currRandomNumber)
        }

        println("viewDidLoad, array has \(quotesMessages.description)")
    }//eom

    /* */
    override func viewWillAppear(animated: Bool) {
        println("viewWillAppear, array has  \(quotesMessages.description)")
    }

   /* */
   override func viewDidAppear(animated: Bool) {
       println("viewDidAppear, array has  \(quotesMessages.description)")
   }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    /* creates a random number */
    func createRandomNum()-> Int {
        var randomNumberRange = UInt32(49)
        var UnsignedRandomNum = arc4random_uniform(randomNumberRange)
        var randomNum = Int(UnsignedRandomNum)

        return randomNum
    }

    /* gets a new data from databases */
    func getNewQuote(randomNum: Int){
        println("random number \(randomNum) created")
        //Temp var's
        var quoteText = ""
        var quoteAuthor = ""

        var DBQuoteURL = "\(QuoteRef)/\(randomNum)"
        var myRootRef =  Firebase(url:DBQuoteURL)
        myRootRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
            if snapshot.value is NSNull {
                // The value is null
            }
            else
            {
                if let quote = snapshot.value["quote"] as? String {
                    //                    println(quote)
                    quoteText = "'\(quote)'"
                    self.message.text = quoteText
                    self.quotesMessages.append(quoteText)
                }
            }
        })

        println("quote is: \(quoteText)")
    }//eom
}//eoc

来自控制台的输出:

random number 24 created
quote is: 
random number 18 created
quote is: 
random number 45 created
quote is: 
random number 47 created
quote is: 
random number 34 created
quote is: 
viewDidLoad, array has []
viewWillAppear, array has  []
viewDidAppear, array has  []

Iphone截图: enter image description here

2 个答案:

答案 0 :(得分:3)

您遇到了异步方法的精彩问题!

我不知道你是否知道这一点,但是异步代码会在其他所有内容继续运行时运行,即代码不会等待其完成继续。

这里发生的是你的循环到达myRootRef.observeSingleEventOfType...部分,启动异步调用,然后继续前进,而不必完成所有代码。

这就是它看起来像是不按顺序循环,或者从来没有被填满等等。

我不确定您对self.message.text = quoteText getNewQuote内的myRootRef.observeSingleEventOfType...想要做些什么,但是按照您拥有它的方式,它只会使用最近下载的内容更新您的标签报价。

如果您想在if let quote = snapshot.value["quote"] as? String {.......}代码段内发生某些事情,请确保它在if quotesMessages.count == 5 {...}的大括号内。 如果你想在完成下载后做到这一点,你可以在if let内,或者观察者或任何你想要的地方尝试一个计数器SELECT DISTINCT

祝你好运!

答案 1 :(得分:2)

.Value将返回指定节点的所有子节点。因此,如果您有一个名为Quote的节点和322个子节点,则使用.Value将返回所有322个子节点以及每个子节点子节点。如果要使用每个子节点填充数组,则应进行观察.Value调用,然后在下面的{}内,迭代返回的快照以填充数组。

override func viewDidLoad() {
        super.viewDidLoad()

        self.fillArray()


    func fillArray() {
      myRootRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
         if snapshot.value is NSNull {

         } else {
           //init myArray var and then fill with values
           for child in snapshot {
               myArray.append(child.value)
           }

           //now that we have filled the array, we can generate
           //  random numbers and pull quotes from it
         }
      })
}

请注意,在observeSingleEvent调用块完成之前,我们不会执行任何其他处理。因此,如果您想从中提取数据,则必须在该块内完成。请记住,Firebase的强大功能是异步性质,因此当您的应用等待Firebase中的数据返回时,其他任务正在进行中。

第二件事是,如果期望的结果是生成随机数并使用它来从Firebase读取引用,您可能需要考虑查询。

因此Firebase数据的结构如下:

Quotes
   autogenerated_child_node_name0
      quote: "No matter where you go, there you are"
      index:  1
   autogenerated_child_node_name1
      quote: "Don't call me Shirley"
      index:  2

现在你可以避免阅读所有322个引号!生成一个随机数,在这种情况下为1,并查询报价为1的报价,并且您的报价没有读入所有报价。

记住;需要制作一个循环,在查询块完成之前不会查询下一个引用。这可以通过while循环和块内的isDone = YES / NO变量来完成。当块完成isDone = YES时,while循环将执行下一个查询。