我正在尝试从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编程的新手,所以非常感谢任何帮助。
答案 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
}
..
}
}