我正在为我的应用程序开发一些代码在macOS上使用DispatchQueue同步但我不知道如何正确使用它。
有一个函数必须按顺序输出:
<我>,我>
public func a (_ sender: AnyObject) {
var response: [String] = [ ]
DispatchQueue.global().sync { // Correct
requestUrlFunct(urlString: "https://hostname.com") { (a) in a.enumerateLines { line, _ in
if( line != "" ){
response.append(line)
////EDIT: here i have to populate a popup. Someting like popup?.addItem(withTitle: line) and if it's not syncronous I've got a core error
}
}
print(response)
}
}
print("A")
//here something like self.popup.isEnabled = true;
}
这个函数调用:
public func requestUrlFunct(urlString: String, completionBlock: @escaping ([Any]) -> Void) -> Void {
let requestURL = URL(string: urlString)
var request = URLRequest(url: requestURL!)
var response: [String] = [ ]
let requestTask = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
let a = String(data: data!, encoding: String.Encoding.utf8) as String!
completionBlock([a!]);
}
DispatchQueue.global().sync {
requestTask.resume()
}
}
,但最后的结果是:
<我>,响应我>
如何填充DispatchQueue
之外的var response: [String] = [ ]
?填不满
在DispatchQueue.global().sync
中包装URL调用不会使URL调用实际上是同步的——URL调用本身仍然是一个异步调用。如果你仔细想想,这是一件非常好的事情——我们不希望我们的程序冻结,例如,如果我们的网络连接没有响应。
在您当前的代码中,func a
运行,然后调用requestUrlFunct
,其中包括异步代码。该异步代码不会自动返回,因此a
继续运行并到达print("A")
行。然后,URL调用返回(异步)并调用回调函数(通过末尾的闭包传递给requestUrlFunct
)。此时,将调用print(response)
行。
你已经使用了你需要使用的概念,那就是"回调函数"。使用回调函数,您可以在获得响应后执行一些代码。这个可能意味着你必须重构你的一些代码,因为你不能指望立即同步响应。例如,您将无法从func a
返回您的响应。
好消息是这将大大清理您的一些代码。您可能会注意到,我使用guard
语句和as?
来避免使用!
强制展开,这可能会导致崩溃。
public func a (_ sender: AnyObject) {
requestUrlFunct(urlString: "https://hostname.com") { responseArray in
DispatchQueue.main.async {
//do something with the response
}
}
//can't access the response here, since it is asynchronous
}
public func requestUrlFunct(urlString: String, completionBlock: @escaping ([String]) -> Void) -> Void {
guard let requestURL = URL(string: urlString) else {
//handle error
return
}
let request = URLRequest(url: requestURL)
let requestTask = URLSession.shared.dataTask(with: request) {
(data: Data?, response: URLResponse?, error: Error?) in
if let data = data, let a = String(data: data, encoding: String.Encoding.utf8) {
completionBlock([a]);
}
}
requestTask.resume()
}
我留下了一个我不太确定的原始工件——requestUrlFunct
回调返回[String]
的事实,但它只会返回一个项目(因为响应通过执行[a]
变成了一个数组)——当你做一些重构时,这是你可能想要看的东西。
还值得注意的是,大多数情况下,对于回调函数,您还希望在出现错误时发生某种回调。现在,根本没有错误处理。