如何正确检索firebase数据库?

时间:2016-06-03 01:28:54

标签: ios swift firebase firebase-realtime-database

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

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
}

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

div.innerHTML = div.innerHTML + messages.join('');

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

我认为我遗漏了一些关于swift或firebase的基本信息。我是iOS编程的新手,所以非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

只有在第一个观察者内部,您将获得值,返回将始终为nil,这是因为只有返回尝试以同步方式工作,而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中的异步执行和回调。

答案 1 :(得分:3)

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