Dav*_*eek 12 ios firebase swift firebase-realtime-database
我dispatch_group用来调用Firebase请求函数,并在请求完成后得到通知,以便能够处理结果.在这种情况下,我刚刚发布了一个print语句.
func loadStuff() {
dispatch_group_enter(group)
myFirebaseFunction() {
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
Run Code Online (Sandbox Code Playgroud)
这段代码工作正常.问题是,在运行时,数据将添加到Firebase数据库中.这就是为什么我必须使用observeEventType而不是observeSingleEventOfType.
这意味着在运行时期间有一个观察者,如果数据已添加到数据库中,myFirebaseFunction则将再次调用其中的块.
一旦发生这种情况,应用程序崩溃,因为dispatch_group_leave(group)没有调用dispatch_group_enter(group).只要我做对了.
dispatch_group_enter(group)
myFirebaseFunction() {
dispatch_group_leave(group) // crash here
}
Run Code Online (Sandbox Code Playgroud)
如果我将其更改为observeSingleEventOfType,则不会发生崩溃,但不会观察到新添加的数据到Firebase.
使用dispatch_group多个运行Web服务的最佳实践是什么?或者我该怎么做才能解决我的问题?非常感谢帮助.
PS目前我正在使用Swift 2.3,但计划升级到Swift 3,所以收到两者兼有的答案会非常棒.
Mat*_*man 16
如你所说,呼叫dispatch_group_enter和dispatch_group_leave必须平衡.在这里,您无法平衡它们,因为执行实际实时获取的函数只会调用leave.
如果您myFirebaseFunction始终对该调度组执行其工作没有任何问题,那么您可以将enter和leave放在那里,可能使用beginHandler和completionHandler:
func loadStuff() {
myFirebaseFunction(beginHandler: {
dispatch_group_enter(group)
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}, completionHandler: { dispatch_group_leave(group) })
}
func myFirebaseFunction(beginHandler: () -> (), completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
beginHandler()
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
Run Code Online (Sandbox Code Playgroud)
在这里,完成处理器仍然会被设置为dispatch_group_leave通过loadStuff,但也有开始处理程序,它会叫dispatch_group_enter也dispatch_group_notify.需要在begin中调用notify的原因是我们需要确保在调用notify之前已经进入组,或者如果组为空则通知块将立即执行.
传递给的块dispatch_group_notify只会被调用一次,即使在调用notify之后对组执行了块也是如此.因此,每个自动呼叫observeEventType在组上发生可能是安全的.然后,在这些函数之外的任何时候,您需要等待加载完成,您只需调用notify即可.
编辑:因为每次调用时beginHandler都会调用notify,所以此方法实际上会导致每次调用notify块,因此它可能不是理想的选择.
如果你真正需要的只是第一次observeEventType使用该组的调用,那么一个选项是有两个版本myFirebaseFunction:一个类似于你已经拥有的一个和一个使用的版本observeSingleEventOfType.然后加载东西可以调用这两个函数,只dispatch_group_leave作为完成传递给其中一个:
func loadStuff() {
dispatch_group_enter(group)
myInitialFirebaseFunction() {
dispatch_group_leave(group)
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
myFirebaseFunction({})
}
func myInitialFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
processSnapshot(snapshot)
completionHandler()
})
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeSingleEventOfType(.Value, withBlock: { snapshot in
processSnapshot(snapshot)
completionHandler()
})
}
func processSnapshot(snapshot: FDataSnapshot) {
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
}
Run Code Online (Sandbox Code Playgroud)
请注意,因为loadStuff在"方法2"中基本上从Firebase加载了两次,所以它可能不如您所希望的那样高效.在这种情况下,您可以使用a Bool来确定是否应该调用leave:
var shouldLeaveGroupOnProcess = false
func loadStuff() {
dispatch_group_enter(group)
shouldLeaveGroupOnProcess = true
myFirebaseFunction() {
if shouldLeaveGroupOnProcess {
shouldLeaveGroupOnProcess = false
dispatch_group_leave(group)
}
}
dispatch_group_notify(group, dispatch_get_main_queue()) {
print("done")
}
}
func myFirebaseFunction(completionHandler: () -> ()) {
let usersRef = firebase.child("likes")
usersRef.observeEventType(.Value, withBlock: { snapshot in
if snapshot.exists() {
let sorted = (snapshot.value!.allValues as NSArray).sortedArrayUsingDescriptors([NSSortDescriptor(key: "date",ascending: false)])
for item in sorted {
dict.append(item as! NSDictionary)
}
}
completionHandler()
})
}
Run Code Online (Sandbox Code Playgroud)
这里,即使observeEventType在初始加载期间进行多次调用,也leave可以保证仅调用一次并且不会发生崩溃.
PS目前我正在使用Swift 2.3,但计划升级到Swift 3,所以收到两者兼有的答案会非常棒.
Dispatch已经在Swift 3中得到了彻底的改进(它是面向对象的),所以代码在两者上运行良好并不是真的:)
但是上述三种方法中的每一种的概念都是相同的.在Swift 3中:
DispatchGroupdispatch_group_enter现在enter是组上的实例方法dispatch_group_leave现在leave是组上的实例方法dispatch_group_notify现在notify是组上的实例方法| 归档时间: |
|
| 查看次数: |
3730 次 |
| 最近记录: |