我正在尝试使用 Swift 中的 NSURLSession 同时下载多个文件。我想将所有下载进度状态合并为一个,以便在下载所有文件时显示 100%。目前,每个文件下载完成后我都会获得 100%,但只有在所有文件都已下载时我才需要 100%。我怎样才能在 Swift 中做到这一点?
这是我的下载管理器类:
class DownloadManager : NSObject, URLSessionDelegate, URLSessionDownloadDelegate {
static var shared = DownloadManager()
var task1Progress = 0.00
var task2Progress = 0.00
typealias ProgressHandler = (Float) -> ()
var onProgress : ProgressHandler? {
didSet {
if onProgress != nil {
let _ = activate()
}
}
}
override private init() {
super.init()
}
func activate() -> URLSession {
let config = URLSessionConfiguration.background(withIdentifier: "\(Bundle.main.bundleIdentifier!).background")
// Warning: If an URLSession still exists from a previous download, it doesn't create a new URLSession object but returns the existing one with the old delegate object attached!
return URLSession(configuration: config, delegate: self, delegateQueue: OperationQueue())
}
func calculateProgress(session : URLSession, completionHandler : @escaping (Float) -> ()) {
session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
let progress = downloads.map({ (task) -> Float in
if task.countOfBytesExpectedToReceive > 0 {
return Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive)
} else {
return 0.0
}
})
completionHandler(progress.reduce(0.0, +))
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
if totalBytesExpectedToWrite > 0 {
if let onProgress = onProgress {
calculateProgress(session: session, completionHandler: onProgress)
}
let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
debugPrint("Download Progress \(downloadTask) \(progress)")
}
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
debugPrint("Download finished: \(location)")
try? FileManager.default.removeItem(at: location)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
debugPrint("Task completed: \(task), error: \(String(describing: error))")
}
private func calculateProgress(session : URLSession, completionHandler : @escaping (Float) -> ()) {
session.getTasksWithCompletionHandler { (tasks, uploads, downloads) in
let progress = downloads.map({ (task) -> Float in
if task.countOfBytesExpectedToReceive > 0 {
if (task.taskIdentifier == 1) {
self.task1Progress = Double(Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive))
} else if (task.taskIdentifier == 2){
self.task2Progress = Double(Float(task.countOfBytesReceived) / Float(task.countOfBytesExpectedToReceive))
}
print("pro1 = \(self.task1Progress) pro2 = \(self.task2Progress)")
if(self.task1Progress>0.0000 && self.task2Progress>0.000) {
return Float(min(self.task1Progress ,self.task2Progress))
}
return Float(max(self.task1Progress ,self.task2Progress))
} else {
return 0.0
}
})
completionHandler(progress.reduce(0.0, +))
}
}
最佳答案
您可以使用 dispatchgroup tp 实现所需的行为。
要下载文件,您将调用 downloadManager
的共享方法。在 dispatchGroup 上调度下载操作,在通知中,您将在所有文件下载完成后收到回调。
请在下面找到示例:
func dispatchGroupUsage (completion: CallBack) {
let backgroundQ = DispatchQueue.global(attributes: .qosDefault)
let group = DispatchGroup()
for number in numberOfFilesToBeDownloaded {
group.enter()
backgroundQ.async(group: group, execute: {
// call download manager's method to download files
group.leave()
})
}
group.notify(queue: DispatchQueue.main, execute: {
print("All Done"); completion(result: fill)
})
}
关于ios - 如何在 Swift 中将多个子进度聚合为一个主进度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49511459/