同步不同步,无法填充阵列调度队列



我正在为我的应用程序开发一些代码在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]变成了一个数组)——当你做一些重构时,这是你可能想要看的东西。

还值得注意的是,大多数情况下,对于回调函数,您还希望在出现错误时发生某种回调。现在,根本没有错误处理。

最新更新