如何正确检索 firebase 数据库?

How to retrieve firebase database properly?

我正在尝试从 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 闭包内打印(episode.description),它工作正常。但是如果我在外面打印它是空的。

我想我遗漏了一些关于 swift 或 firebase 的基本知识。我是 iOS 编程新手,如有任何帮助,我们将不胜感激。

所有 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可以这样

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
        }
        ..
    }
}

只有在第一个观察者中你才会有值 return 永远是 nil,这是因为只有 return 试图以同步方式工作,而 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 中有关异步执行和回调的内容。