【问题标题】:How can I download datas from multiple URL in concurrency mode?如何在并发模式下从多个 URL 下载数据?
【发布时间】:2015-06-24 10:11:01
【问题描述】:

我已尝试使用此link 仅下载一个 URL。也成功地为暂停和恢复工作。

现在我正在尝试多个 URL(即 5 个 URL)。如果第二个 URL 正在进行,那么如果我启动第三个 URL 意味着,第二个停止。

我不知道并发运行所有 url。我尝试过使用 NSOperationQueue。但我不知道确切的语法,也不知道如何在队列中添加任务。

我的 URL 链接之间不应有任何中断。该怎么做?

我的代码:

var dict = [NSURLSessionTask:Int]()

lazy var session : NSURLSession = {
        let config = NSURLSessionConfiguration.ephemeralSessionConfiguration()

        config.allowsCellularAccess = false
        let session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())

        println(session)
        return session

        }()

func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
        if let numberOfTask = dict[downloadTask]
    {
        println("which task is this\(dict[downloadTask])")

        println("downloaded \(100*writ/exp)")
        taskTotalBytesWritten = Int(writ)
        taskTotalBytesExpectedToWrite = Int(exp)
        percentageWritten = Float(taskTotalBytesWritten) / Float(taskTotalBytesExpectedToWrite)

        downLoadTblVw.delegate = self
        downLoadTblVw.reloadData()
    }
     }

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {


        // unused in this example
    }

    func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) {
        println("completed: error: \(error)")
    }

    // this is the only required NSURLSessionDownloadDelegate method

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

        let documentsDirectoryURL =  NSFileManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).first as NSURL
        println("Finished downloading!")
        println(documentsDirectoryURL)
        var err:NSError?

        // Here you can move your downloaded file
        if NSFileManager().moveItemAtURL(location, toURL: documentsDirectoryURL.URLByAppendingPathComponent(downloadTask.response!.suggestedFilename!), error: &err) {
            println("File saved")
        } else {
            if let err = err {
                println("File not saved.\n\(err.description)")

            }
        }

    }



    @IBAction func startDownload(sender: UIButton) {
        var btnPos: CGPoint = sender.convertPoint(CGPointZero, toView: downLoadTblVw)
        var indePath: NSIndexPath = downLoadTblVw.indexPathForRowAtPoint(btnPos)!

        println("INDE\(indePath.row)")

        buttonTag = indePath.row

        if self.task != nil {

            println("PRESSED TASK NIL")
            return
        }

        switch(buttonTag)
        {
        case 0:

            var myQueue = NSOperationQueue()
            myQueue.addOperationWithBlock({

                let s = "https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/MobileHIG/MobileHIG.pdf"
                let url = NSURL(string:s)!
                let req = NSMutableURLRequest(URL:url)
                let task = self.session.downloadTaskWithRequest(req)
                self.task = task

                dict[task] = 0
                println("SESSION -> task \(task)")

                task.resume()
                println("PRESSED SECOND TIME")
            })
            break

        case 1:

  let s = "https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/iphoneappprogrammingguide.pdf"
            let url = NSURL(string:s)!
            let req = NSMutableURLRequest(URL:url)

            var myQueue = NSOperationQueue()
            myQueue.addOperationWithBlock({

                let task = self.session.downloadTaskWithRequest(req)
                self.task_1 = task
                dict[task_1] = 1
                println("SESSION _1-> task \(task)")
                task.resume()

                })
            break

        case 2:

            let s = "http://manuals.info.apple.com/MANUALS/1000/MA1565/en_US/iphone_user_guide.pdf"
            let url = NSURL(string:s)!
            let req = NSMutableURLRequest(URL:url)
            let task = self.session.downloadTaskWithRequest(req)
            self.task_2 = task
            dict[task_2] = 2
            println("SESSION _2-> task \(task)")
            task.resume()
            break

        case 3:

            let s = "https://developer.apple.com/library/ios/documentation/AudioVideo/Conceptual/AVFoundationPG/AVFoundationPG.pdf"
            let url = NSURL(string:s)!
            let req = NSMutableURLRequest(URL:url)
            let task = self.session.downloadTaskWithRequest(req)
            self.task_3 = task
            dict[task_3] = 3
            println("SESSION _3-> task \(task)")
            task.resume()

            break
        default:
            println("WRONG BUTTON PRESSED")
            break
        }
      }

【问题讨论】:

    标签: swift cocoa-touch ios8 nsoperation nsoperationqueue


    【解决方案1】:

    您可以使用库Alamofire 来处理这种情况。本质是使用多个线程从 URL 中获取数据并调用一些回调函数来处理数据。你可以阅读图书馆的文档。

    【讨论】:

    • 请添加一个如何使用建议库的示例
    • @McDonal_11 您可以按顺序编写代码以使用库获取 url。它们将以调用回调函数结束。线程将同时运行。你读过图书馆的文档吗?
    【解决方案2】:

    您的下载代码看起来不错。按下按钮时,下载任务将开始。 (比如我点击button_2和button_3,会同时下载2和3的下载任务)

    您的代码中的缺陷在于

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

    由于您想跟踪每个任务的进度,您必须找到发送此委托调用的 downloadTask

    要跟踪哪个任务触发了委托,您可以执行以下操作

    let dict = [NSURLSessionTask:Int]()
    
    let task1 = session.DownloadTaskWithURL( ..... ) 
    let task2 = session.DownloadTaskWithURL( ..... ) 
    
    dict[task1] = 0
    dict[task2] = 1
    

    并且在委托调用中,您可以获得与您设置的数字相对应的任务

    func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten writ: Int64, totalBytesExpectedToWrite exp: Int64) {
        if let numberOfTask = dict[downloadTask]{
            progress[numberOfTask] = Float(taskTotalBytesWritten) / Float(taskTotalBytesExpectedToWrite)
            downLoadTblVw.reloadData()
        }
    }
    

    【讨论】:

    • 但是,我需要在进度视图中显示下载进度。 @nRewik
    • 我怎样才能做到这一点??
    • 嗨.. @nRewik 。苏?有疑问。
    • 同样的事情正在发生。如果第二个 URL 正在进行,那么如果我启动第三个 URL 意味着,第二个停止。 @nRewik
    • 嗨@nRewik。请帮助我。
    猜你喜欢
    • 2021-07-26
    • 2016-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多