【问题标题】:How to retrieve firebase database properly?如何正确检索firebase数据库?
【发布时间】:2016-06-03 01:28:53
【问题描述】:

我正在尝试从 firebase 数据库中检索数据。但是,我无法将本地变量分配给数据库的值。我正在使用以下类和方法。

class Episode {

var title: String?
var description: String?
var location: String?
var discount: String?
var star: Int?

init() {
    self.title = ""
    self.description = ""
    self.location = ""
    self.discount = ""
    self.star = 0
}

这是我从数据库中提取数据的方法

func getValues() -> Episode {
    let rootRef = FIRDatabase.database().reference().child("Restaurants").child("The Kafe")
    let descriptionRef = rootRef.child("Description")
    let discountRef = rootRef.child("Discount")
    let locationRef = rootRef.child("Location")
    let starRef = rootRef.child("Star")
    let episode = Episode()

    descriptionRef.observeEventType(.Value) { (snap: FIRDataSnapshot) in
        episode.description = snap.value as? String
    }
    discountRef.observeEventType(.Value) { (snap: FIRDataSnapshot) in
        episode.discount = snap.value as? String
    }
    locationRef.observeEventType(.Value) { (snap: FIRDataSnapshot) in
        episode.location = snap.value as? String
    }
    starRef.observeEventType(.Value) { (snap: FIRDataSnapshot) in
        episode.star = snap.value as? Int
        print(episode.description!)
    }
    return episode
}

当我打印出返回剧集的值时,它们都是空的。但是,当我在闭包本身中打印值时(例如,如果我在 obserEventType 闭包中执行 print(episode.description),它工作正常。但如果我在外面打印它是空的。

我认为我缺少关于 swift 或 firebase 的一些基本知识。我是 iOS 编程新手,因此我们将不胜感激。

【问题讨论】:

    标签: ios swift firebase firebase-realtime-database


    【解决方案1】:

    只有在第一个观察者内部,才会有返回值始终为零,这是因为只有返回值试图以同步方式工作,而 firebase 将始终以异步方式工作

    rootRef.observeEventType(.Value, withBlock: {(snap) in
            let ep: Dictionary<String,AnyObject?> = [
                "title": snap.childSnapshotForPath("Title").value as? String,
                "description": snap.childSnapshotForPath("Description").value as? String,
                "location": snap.childSnapshotForPath("Location").value as? String,
                "discount": snap.childSnapshotForPath("Discount").value as? String,
                "star": (snap.childSnapshotForPath("Star").value as? NSNumber)?.integerValue,
            ]
            //Here you have your data in your object
            episode = Episode(key: snap.key, dictionary: ep)
        })
    
    rootRef.observeEventType(.Value) { (snap: FIRDataSnapshot) in
        print(snap.childSnapshotForPath("Title").value as? String)
    }
    
    return episode!
    

    此外,如果您想从类似的函数中获取它,您可能应该使用observeSingleEventType。

    您需要重新考虑代码流程,因为您希望 firebase 在始终异步时能够同步工作。你拥有 getValues 函数的方式永远不会奏效。

    要解决这个问题,您应该快速阅读有关异步执行和回调的信息。

    【讨论】:

    • 感谢您的澄清。我对 swift 很陌生,所以我还在研究很多东西。能简单解释一下同步和异步的区别是什么?
    • 同步就是代码会逐行执行,异步就是代码的不同部分在不同的时间以不同的顺序执行,你无法控制执行的顺序。实际上,根据定义,swift在块代码中像按钮事件一样随机执行......作为程序员,您不知道用户何时会单击按钮,但您需要一个事件来处理用户单击按钮时发生的事情。 ..与firebase相同,您不知道firebase何时会给您db信息,但您仍然需要处理它
    • github.com/firebase 在这里你可以找到一些由firebase制作的关于它如何与iOS一起工作的例子,也许这会帮助你理解这个想法......如果你有疑问......你可以随时在这里再问
    【解决方案2】:

    所有 Firebase 事件都是异步的,因此它们以非顺序方式执行,这就是为什么您只能访问回调上下文中的数据...如果您在回调之外放置打印,它将在其中执行一种同步方式,因此它在回调之前执行,这就是它处于初始状态的原因

    1) 你只需要rootRef,剩下的删掉

     let ref = FIRDatabase.database().reference().child("Restaurants").child("The Kafe")
    

    2) 你只需要一个观察者

    var episode:Episode? = nil
    
    rootRef.observeEventType(.Value,withBlock: {(snap) in
    
       let ep:Dictionary<String,AnyObject?> = [
           "title":snap.childSnapshotForPath("title").value as? String,
           //Etc...
           "star":(snap.childSnapshotForPath("price").value as? NSNumber)?.integerValue,
        ]
    
        //Here you have your data in your object
        episode = Episode(key:snap.key,dictionary:ep)
    
    
    }
    

    3) 你的剧集类可以是这样的

    class Episode {
    
        private var _key:String!
        private var _title:String?
        //Etc.....
        private var _star:Int?
    
        var key:String!{
            return _key
        }
        var title:String?{
            return _title
        }
        //Etc....
        var star:Int?{
            return _star
        }
    
        init(key:String!, title:String?,//etc...., star:Int?){
            self._key = key
            self._title = title
            //Etc....
        }
    
        init(key:String,dictionary:Dictionary<String,AnyObject?>){
    
            _key = key
    
            if let title = dictionary["title"] as? String{
                self._title = title
            }
            //Etc...
            if let star = dictionary["star"] as? Int{
                self._star = star
            }
            ..
        }
    }
    

    【讨论】:

    • 感谢您的帮助!但由于某种原因,在调用“episode = Episode(key:snap.key,dictionary:ep)”之后,我仍然得到 nil。您知道是什么原因造成的吗?
    • 您能否更新您的代码以查看您目前的情况
    • 我又遇到了同样的问题,在封闭内打印可以工作,但在外面打印会给我 nil
    猜你喜欢
    • 1970-01-01
    • 2017-07-22
    • 2016-11-22
    • 2016-11-27
    • 1970-01-01
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多