如何使用 NSURLSession 下载多个文件

How to download Multiple Files using NSURLSession

我有问题。我正在尝试使用 NSURLSession 进行多次下载,但我没有明白我做错了什么?此 class 在 class 中初始化一次 X.startDownload(realm.objects(Music)[indexPath.row]) 可能在同一个 class 中被调用多次。问题在class'Download',我肯定知道。如果您需要更多信息,请写信

class Download: NSObject, NSURLSessionDelegate {
var progress: Float = 0.0
var progressBar: UIProgressView?
var addButton: UIButton?


private var downloadTask: [NSURLSessionDownloadTask] = []
private var backgroundSession: [NSURLSession] = []
private let realm = try! Realm()

private var downloadObject:[Music] = []
private var queueObjects:[Music] = []


func startDownload(object: Music? = nil) {
    if (object != nil) {
        self.queueObjects.append(object!)
    }
    let url = queueObjects[queueObjects.startIndex].url

    if downloadTask.count < 3 {
        let backgroundSessionConfiguration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("backgroundSession"+String(queueObjects.count))
        backgroundSession.append(NSURLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: NSOperationQueue.mainQueue()))
        let sessionIndex = backgroundSession.endIndex-1
        backgroundSession[sessionIndex].sessionDescription = String(sessionIndex)

        downloadTask.append(backgroundSession[sessionIndex].downloadTaskWithURL(NSURL(string: url)!))
        let taskIndex = downloadTask.endIndex-1
        downloadTask[taskIndex].taskDescription = String(taskIndex)
        downloadTask[taskIndex].resume()

        downloadObject.append(queueObjects[queueObjects.startIndex])
        queueObjects.removeAtIndex(queueObjects.startIndex)
    }
}

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {

    let index = Int(downloadTask.taskDescription!)!
    print("Index "+String(index))
    let range = downloadObject[ index ].url.rangeOfString("?")!.startIndex.advancedBy(0)
    let url = downloadObject[ index ].url[downloadObject[index].url.startIndex..<range]
    let theFileName = (url as NSString).lastPathComponent
    let path = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
    let directoryPath:String = path[0]
    let fileManager = NSFileManager()
    let destinationURLForFile = NSURL(fileURLWithPath: directoryPath.stringByAppendingString( "/"+theFileName))

    if fileManager.fileExistsAtPath(destinationURLForFile.path!){
        print(destinationURLForFile.path!)
        saveObject(downloadObject[index], path: destinationURLForFile.path!)
    }
    else{
        do {
            try fileManager.moveItemAtURL(location, toURL: destinationURLForFile)
            print(destinationURLForFile.path!)
            saveObject(downloadObject[index], path: destinationURLForFile.path!)
        } catch {
            print("An error occurred while moving file to destination url")
        }
    }
    if addButton != nil {
        addButton?.hidden = true
    }
    downloadTask.cancel()
    session.invalidateAndCancel()

    self.backgroundSession[Int(session.sessionDescription!)!].invalidateAndCancel()
    self.backgroundSession.removeAtIndex(Int(session.sessionDescription!)!)
    self.downloadTask[Int(downloadTask.taskDescription!)!].cancel()
    self.downloadTask.removeAtIndex(Int(downloadTask.taskDescription!)!)
}

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
    progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
    if progressBar != nil {
        progressBar?.progress = progress
    }
}

private func saveObject(object: Music, path: String) {
    let downloadMusic = DownloadMusic()
    downloadMusic.id = object.id
    downloadMusic.owner_id = object.owner_id
    downloadMusic.artist = object.artist
    downloadMusic.title = object.title
    downloadMusic.duration = object.duration
    downloadMusic.path = path

    try! realm.write() {
        realm.add(downloadMusic)
        downloadObject.removeAtIndex(downloadObject.endIndex-1)
        if self.queueObjects.count > 0 {
            self.startDownload()
        }
        print(queueObjects.count)
        print(downloadObject.count)
        print(downloadMusic)
    }
}

}

谢谢

首先,不要那样做。让会话为你限制并发。立即将所有请求扔给它。

其次,除非您的应用刚刚启动,否则不要重新创建后台会话配置。你应该只创建一次,永远不会再创建它。指向同一个标识符的多个 NSURLSession 对象的行为是,IIRC,未定义。

第三,在完成之前不要使会话无效。您将在第一个请求完成后立即取消所有未完成的请求。

第四,你不应该取消任务,除非你想停止正在进行的任务。如果任务已经完成,则取消它没有任何作用。

除此之外,我同意那些人的说法,他们说您需要先解释代码哪里出了问题,然后我才能提供进一步的帮助。 :-)