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