将变量传递给数据任务异步函数



>我正在异步发送HTTP请求,我想以某种方式将局部变量传递到该任务的完成处理程序中。问题是变量在执行 dataTask 后立即发生变化,所以我需要复制该变量。

var neededVariable = 1
for _ in 0...10 {
    let urlS = "https://sub2pewdiepie.com/subscribe.php?param1=123"
    let url = URL(string: urlS.addingPercentEncoding(withAllowedCharacters: 
CharacterSet.urlQueryAllowed)!)!
    let session = URLSession.shared
    let request = URLRequest(url: url)
    let task = session.dataTask(with: request as URLRequest, completionHandler: 
    { data, response, error in
        guard error = nil else {return}
        guard let data = data else {return}
        do {
            print(neededVariable) 
            // code goes here...
        } catch let error { print(error.localizedDescription) }
    })
    task.resume()
    neededVariable += 1
    // code goes here...
}

当然,这将打印增加(N 倍(的值。如何在初始化任务期间修复我的变量?

为此,DispatchGroup 是推荐的 API 例如

var neededVariable = 1
let group = DispatchGroup()
let session = URLSession.shared
for _ in 0...10 {
    group.enter()
    let urlS = "https://sub2pewdiepie.com/subscribe.php?param1=123"
    let url = URL(string: urlS.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)!
    let task = session.dataTask(with: url, completionHandler: { data, response, error in
        defer(group.leave())
        if let error = error { print(error); return }
        do {
            neededVariable += 1
            print(neededVariable) 
        } catch let error { print(error.localizedDescription) }
    })
    task.resume()       
}
group.notify(queue: DispatchQueue.main) {
   print("notify", neededVariable)
}

尝试使用一些工具进行线程管理。例如:信号量。

首先,在数据任务开始之前声明信号量:

let semaphore = DispatchSemaphore(value: 1)

然后重构数据任务代码:

let task = session.dataTask(with: request as URLRequest, completionHandler:
{ [weak self] data, response, error in // don't forget to use weak self to avoid memory leaks
    guard let `self` = self else { return }
    self.semaphore.wait()
    guard error = nil else {
        self.semaphore.signal()
        return
    }
    guard let data = data else {
        self.semaphore.signal()
        return
    }
    // you should not use do block here
    //do { 
    print(self.neededVariable)
    //} catch let error { print(error.localizedDescription) }
    self.semaphore.signal()
})

当然还有:

task.resume()
semaphore.wait()
neededVariable = 2

希望它有帮助!

最新更新