0
我的应用程序同时下载多个文件。我的场景如下:swift iOS - NSURLSession没有正确下载多个文件
- 用户单击下载按钮。
- 下载UITableViewCell初始化,实现NSURLSessionDelegate以下载指定文件。
- 开始下载。下载单元显示正在使用NSURLSession提供的委托下载文件时的进度。
- 该文件在本地保存在文档文件夹中。
- 用户单击一个按钮清除所有完成的下载。此按钮清除Download Cell使用的数组'downloadQueue'。该按钮还调用tableView.reloadData来更新tableView
问题是,当用户启动多个下载时,没有问题发生。所有文件同时正确下载。但是,当用户单击第5步中描述的按钮,然后尝试下载另一个文件时,下载进度立即显示100%完成。并没有文件保存在本地。这可能是由于didFinishDownloadingToURL被立即调用。
这里是我的DownloadCell.swift
class DownloadCell: UITableViewCell, NSURLSessionDelegate {
@IBOutlet weak var lblSongName: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var progressCount: UILabel!
var song: Song!
var task: NSURLSessionTask!
var percentageWritten: Float = 0.0
var taskTotalBytesWritten = 0
var taskTotalBytesExpectedToWrite = 0
lazy var session: NSURLSession = {
let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()
config.allowsCellularAccess = false
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
return session
}()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
func startDownload() {
lblSongName.text = song.songName
if self.task != nil {
return
}
let url = NSURL(string: song.songDownloadLink)!
let req = NSMutableURLRequest(URL: url)
let task = self.session.downloadTaskWithRequest(req)
self.task = task
task.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
taskTotalBytesWritten = Int(writ)
taskTotalBytesExpectedToWrite = Int(exp)
percentageWritten = Float(taskTotalBytesWritten)/Float(taskTotalBytesExpectedToWrite)
progressBar.progress = percentageWritten
progressCount.text = String(Int(percentageWritten*100)) + "%"
print("(\(taskTotalBytesWritten)/\(taskTotalBytesExpectedToWrite))")
}
func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
if error != nil {
print("Completed with error: \(error)")
}
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
do {
let documentsDirectoryURL = NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL!
progressCount.text = "Done!"
progressBar.progress = 100.0
try NSFileManager().moveItemAtURL(location, toURL: documentsDirectoryURL.URLByAppendingPathComponent(song.songName + ".mp3"))
//Handling Badge Values
let tabBar = UIApplication.sharedApplication().keyWindow?.rootViewController as! UITabBarController
let downloadVC = tabBar.viewControllers?[1] as! DownloadViewController
let badgeValue = Int(downloadVC.tabBarItem.badgeValue!)! - 1
downloadVC.tabBarItem.badgeValue = String(badgeValue)
if badgeValue == 0 {
downloadVC.tabBarItem.badgeValue = nil
}
} catch {
print("Error occurred during saving.")
progressCount.text = String(error)
}
}
}
单元格正在重新使用。我不明白为什么设置进度栏值为零与任何事情有关,因为文件甚至没有被下载。让我感到困惑的是,当文件连续下载时,它工作得很好。此问题仅在阵列被清除然后重新填充时才存在。另外,你能解释一下实现prepareForReuse吗? – krypton36
在startdownload函数的第5行放置了一个断点。 (在“return”行) – Vlk
第5步之后,代码应该运行到您的断点。因为你说过使用tableView.reloadData来更新tableView。但reloadData使用dequeueReusableCellWithIdentifier调用cellForRowAtIndexpath,使用之前的单元格来制作单元格。这些单元没有被重新初始化,这就是单元重用的要点。所以他们的任务可能仍然不是零。你应该在prepareForReuse(最重要的任务,但progressbar.progress,progressCount.text等)中重置你想要的属性 – Vlk