我正在尝试在 Swift 包中使用 URLSession 下载文件。这是我的代码:
public class Downloader: NSObject, URLSessionDownloadDelegate {
private lazy var session = URLSession(configuration: .default,
delegate: self,
delegateQueue: nil)
var semaphore: DispatchSemaphore?
public func download(fileAt url: URL) {
semaphore = DispatchSemaphore(value: 1)
session.downloadTask(with: url).resume()
semaphore!.wait()
}
public func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten: Int64,
totalBytesExpectedToWrite: Int64) {
print(Float(totalBytesWritten) / Float(totalBytesExpectedToWrite))
}
public func urlSession(_ session: URLSession,
downloadTask: URLSessionDownloadTask,
didFinishDownloadingTo location: URL) {
print(location)
semaphore?.signal()
}
}
问题是,当我尝试使用它时,该应用程序立即存在而无需等待。我知道如何使用闭包回调设置信号量,但这种方法不起作用。我需要获取进度更新,所以我不能关闭方法。
如果有人能帮忙,那就太好了。
这可以通过将semaphore
添加为 self 的属性来完成。它应该在didCompleteWithError
和didFinishDownloadingTo
中发出信号。
我已经解决了我的解决方案,从带有状态代码的包中退出,这是类似情况的示例,首先您必须使用RunLoop
等待线程。
import Foundation
struct Todo: Codable {
let userId: Int
let id: Int
let title: String
let completed: Bool
}
guard let url = URL.init(string: "https://jsonplaceholder.typicode.com/todos/1") else {
fatalError("badURL error")
}
URLSession.shared.dataTask(with: url) { data, response, error in
guard let data = data, error == nil else {
fatalError("error is not nil")
}
guard let todo = try? JSONDecoder().decode(Todo.self, from: data) else {
fatalError("JSONDecoding error")
}
print("Todo ",todo)
exit(EXIT_SUCCESS)
}.resume()
RunLoop.current.run()
DispatchGroup
中的相同意识形态,为了使线程等待而不是立即杀死,请使用RunLoop.current.run()
,当您的方案成功或失败时,请使用带有EXIT_SUCCESS
或EXIT_FAILURE
的退出或任何自定义Int32
变量,如下所示。
public var EXIT_FAILURE: Int32 { get }
public var EXIT_SUCCESS: Int32 { get }