在 Swift 内完成下载后调度?

Dispatch After Download is Finished in Swift?

我正在 swift 中下载文件,下载会话由每个 table 视图单元格上的按钮触发。但是,我不希望下一次下载(如果有人按下另一个单元格上的下载按钮)发生在上一次下载完成之后。

有没有一种方法可以使用 dispatch_after 之类的方法来完成此操作?

如果有帮助的话,这是我下载的代码。

//FUNCTION TO DOWNLOAD THE PDF
//PASS THE ONLINE PDF URL AS NSURL
//ASYNC REQUEST
let defaultSession = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
var dataTask: NSURLSessionDataTask?
var temp_name = String()
var temp_index = Int()
var temp_indexPath = NSIndexPath()

lazy var downloadsSession: NSURLSession = {

    let configuration = NSURLSessionConfiguration.defaultSessionConfiguration()
    let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil)
    return session
}()
func getUrl(name: String) -> NSURL?{
    let documentsUrl =  NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL!
    return documentsUrl.URLByAppendingPathComponent(name)
}

func getIndex() -> Int?{
    return temp_index
}

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

    if let originalURL = downloadTask.originalRequest?.URL?.absoluteString,
        destinationURL =  getUrl(temp_name){

        let fileManager = NSFileManager.defaultManager()
        do {
            try fileManager.removeItemAtURL(destinationURL)
        } catch {
            // Non-fatal: file probably doesn't exist
        }
        do {
            try fileManager.copyItemAtURL(location, toURL: destinationURL)
        } catch let error as NSError {
            print("Could not copy file to disk: \(error.localizedDescription)")
        }
    }


    if let url = downloadTask.originalRequest?.URL?.absoluteString {
        activeDownloads[url] = nil

        if let trackIndex = getIndex() {
            dispatch_async(dispatch_get_main_queue(), {
                defaults.setBool(false, forKey: self.temp_name + "_downloading")


                self.tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: trackIndex, inSection: 0)], withRowAnimation: .None)
            })
        }
    }


}


func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {

    if let downloadUrl = downloadTask.originalRequest?.URL?.absoluteString,
        download = activeDownloads[downloadUrl] {
        download.progress = Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)
        if let trackIndex = getIndex(), let cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: trackIndex, inSection: 0)) as? MainTableViewCell {
            dispatch_async(dispatch_get_main_queue(), {
                cell.progress.progress = download.progress
                if(download.progress < 1.0){
                    cell.progress.hidden = false
                }
                else{
                   cell.progress.hidden = true
                }
            })
        }

    }

}

// Action triggered by UIButton (in this case the download button)
//Access tag, which is the IndexPath.row, using sender.tag
@IBAction func downloadFile(sender: UIButton){
    let indexPath = NSIndexPath(forRow: sender.tag, inSection: 0)
    let cell = tableView.cellForRowAtIndexPath(indexPath) as! MainTableViewCell
    cell.downloadButton.hidden = true
    cell.progress.progress = 0
    cell.progress.hidden = false



    let isAvailable = true
    let key = names[sender.tag] + "_offline"
    defaults.setValue(isAvailable, forKey: key)
    let name = (names[sender.tag])
    let fileName = name + ".pdf"
    let attachment = attachments[sender.tag]
    temp_name = fileName
    temp_index = sender.tag
    temp_indexPath = indexPath
    let destinationURL =  getUrl(temp_name)!
    defaults.setValue(destinationURL.path!, forKey: name + "_path")
    defaults.synchronize()
    defaults.setBool(true, forKey: name + "_downloading")
    let urlString = attachment
    let url =  NSURL(string: urlString)

    let download = PDFDownload(url: urlString)

    download.downloadTask = downloadsSession.downloadTaskWithURL(url!)
    download.downloadTask!.resume()
    download.isDownloading = true

    activeDownloads[download.url] = download

}

有一个布尔值可以存储下载会话是否正在发生,所以也许我可以使用它?等到布尔值是 false 来执行我的代码?

您可以使用 NSOperationQueue 来完成此操作。创建一个 operationqueue 和一个 NSOperation 对象来存储在当前操作之前添加到操作队列的前一个操作。每次点击 tableviewcell 的按钮都会创建新的 NSOperation 实例,然后在将其添加到操作队列之前执行以下操作。

1- 检查 tempoperation 是否为零。然后将当前操作分配给它,然后添加到操作队列。 2. else先添加对tempoperation的依赖,然后将当前操作分配给它,然后添加到操作队列。

这样每个任务都会在上一个任务完成后开始。希望这会帮助你。 :)

@Deepak kumar 的回答是正确的,但是为每个操作添加依赖项并不是一个好主意。 你可以用更简单的方法来做。只需 3 个步骤。

  1. 创建 NSOperationQueue 对象。
  2. 然后将 属性 maxConcurrentOpeations 设置为 1。
  3. 然后将操作添加到队列中,它会一个一个地执行操作。