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

Posted

技术标签:

【中文标题】将firebase数据添加到ios swift中的数组【英文标题】:Adding firebase data to an array in ios swift 【发布时间】:2015-07-26 03:00:27 【问题描述】:

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

这怎么会发生? 导致此问题的 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截图:

【问题讨论】:

我的评论对您的问题有帮助吗? 是和不是。仍在学习如何处理这些类型的异步操作。不得不暂时搁置这个项目。再次感谢 【参考方案1】:

您遇到了异步方法的奇妙问题!

我不知道你是否知道这一点,但是一段异步代码会在其他一切继续进行的同时运行,即你的代码不会等待其完成继续。

这里发生的情况是,您的循环到达 myRootRef.observeSingleEventOfType... 部分,开始异步调用,然后继续运行,而不必完成所有代码。

这就是它看起来像是在无序地通过循环,或者永远不会被填充等等。

我不确定你想用getNewQuote 中的self.message.text = quoteText 做什么,但按照你的方式,它只会用最近下载的报价更新你的标签。

如果您想在myRootRef.observeSingleEventOfType... 代码段中发生某些事情,请确保它位于if let quote = snapshot.value["quote"] as? String ....... 的大括号内。 如果您想在完成下载后实现它,您可以尝试在 if let 内的计数器 if quotesMessages.count == 5 ...,或者观察者或任何您喜欢的方式。

祝你好运!

【讨论】:

【参考方案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 将让 while 循环执行下一个查询。

【讨论】:

以上是关于将firebase数据添加到ios swift中的数组的主要内容,如果未能解决你的问题,请参考以下文章

使用 Swift Package Manager 将 Google Firebase Admob 添加到 iOS 项目 [关闭]

如何使用 iOS Swift 更新 firebase 中的单个数组元素?

FIREBASE 数据库 - 将唯一密钥存储到子节点(Swift/IOS)

Firebase iOS Codelab Swift 中的错误

Swift 3 中的 Firebase 存储图像持久性

在 Swift 3 中将数据添加到 Firebase 而不是 SetValue