我正在使用DispatchGroup.enter()和leave()来处理辅助类的reverseG异步函数。问题很明显,我正在使用mainViewController的对象在helper类中调用mainViewControllers的dispatchGroup.leave()!有办法吗?
在主视图控制器中声明reverseG时,相同的代码有效。
class Geo {
var obj = ViewController()
static func reverseG(_ coordinates: CLLocation, _ completion: @escaping (CLPlacemark) -> ()) {
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(coordinates) { (placemarks, error) in
if let error = error {
print("error: \(error.localizedDescription)")
}
if let placemarks = placemarks, placemarks.count > 0 {
let placemark = placemarks.first!
completion(placemark) // set ViewController's properties
} else {
print("no data")
}
obj.dispatchGroup.leave() // ** ERROR **
}
}
}
主视图控制器的函数调用
dispatchGroup.enter()
Geo.reverseG(coordinates, setValues) // completionHandler: setValues
dispatchGroup.notify(queue: DispatchQueue.main) {
// call another function on completion
}
答案 0 :(得分:1)
每次leave
来电都必须有相关的enter
来电。如果您在没有先调用leave
的情况下致电enter
,它就会崩溃。这里的问题是您在某个群组上呼叫enter
,但reverseG
正在leave
的其他某个实例上呼叫ViewController
。我建议将DispatchGroup
作为参数传递给您的reverseG
方法。或者,更好的是,reverseG
不应该离开该群组,而是将leave
调用放在reserveG
调用的完成处理程序中。
dispatchGroup.enter()
Geo.reverseG(coordinates) { placemark in
defer { dispatchGroup.leave() }
guard let placemark = placemark else { return }
// use placemark here, e.g. call `setValues` or whatever
}
dispatchGroup.notify(queue: DispatchQueue.main) {
// call another function on completion
}
和
class Geo {
// var obj = ViewController()
static func reverseG(_ coordinates: CLLocation, completion: @escaping (CLPlacemark?) -> Void) {
let geoCoder = CLGeocoder()
geoCoder.reverseGeocodeLocation(coordinates) { placemarks, error in
if let error = error {
print("error: \(error.localizedDescription)")
}
completion(placemarks?.first)
// obj.dispatchGroup.leave() // ** ERROR **
}
}
}
这使DispatchGroup
逻辑保持在应用程序的一个级别,使您的类不那么紧密耦合(例如,Geo编码器不需要知道视图控制器是否使用调度组)。 / p>
坦率地说,如果只有一个电话,我就不清楚你为什么要使用调度组。通常,您可以在完成处理程序中放置您调用的任何内容,从而进一步简化代码。如果您正在进行一系列调用,通常只会使用群组。 (也许你只是简化了你的代码片段,而你真正做了多次调用。在这种情况下,调度组可能有意义。但话说回来,你不应该做并发的地理编码请求,完全不同地提出了完全不同的模式。
答案 1 :(得分:0)
通过函数调用将dispatchGroup作为参数传递,并且它有效。
Geo.reverseG(coordinates, dispatchGroup, setValues)
答案 2 :(得分:0)
我的两分钱来展示如何工作: (可能对其他人有用..)
// Created by ing.conti on 02/02/21.
//
import Foundation
print("Hello, World!")
let r = AsyncRunner()
r.runMultiple(args: ["Sam", "Sarah", "Tom"])
class AsyncRunner{
static let shared = AsyncRunner()
let dispatchQueue = DispatchQueue(label: "MyQueue", qos:.userInitiated)
let dispatchGroup = DispatchGroup.init()
func runMultiple(args: [String]){
let count = args.count
for i in 0..<count {
dispatchQueue.async(group: dispatchGroup) { [unowned self] in
dispatchGroup.enter()
self.fakeTask(arg: args[i])
}
}
_ = dispatchGroup.wait(timeout: DispatchTime.distantFuture)
}
func fakeTask(arg: String){
for i in 0..<3 {
print(arg, i)
sleep(1)
}
dispatchGroup.leave()
}
}