问题
I have tried this link for download only one URL. Successfully working for pause and resume too.
Now I am trying for multiple URL (i.e, for 5 URL). If 2nd URL is progressing, on that time if I start third URL means, 2nd is stopped.
I don't know to run all url in concurrency. I have tried with NSOperationQueue. But I don't know exact syntax and also I don't know how to add task in Queue.
There should not be any interruption between my URL links. How to do that?
My code:
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
}
}
回答1:
You can use the library Alamofire to handle this situation. The essence is to use multiple threads to fetch data from URLs and call some callback function to handle the data. You can read the docs of the library.
回答2:
Your download code look fine. When the button is pressed the download task will begin. ( For example, If I click at button_2 and button_3, the download task of 2 and 3 will be downloaded simultaneously )
The flaw in your code is at
func URLSession(session: NSURLSession,
downloadTask: NSURLSessionDownloadTask,
didWriteData bytesWritten: Int64,
totalBytesWritten writ: Int64,
totalBytesExpectedToWrite exp: Int64)
Since you want to keep track the progress of each task, you have to find which downloadTask
that send this delegate call.
To keep track which task fire the delegate, you can do something like this
let dict = [NSURLSessionTask:Int]()
let task1 = session.DownloadTaskWithURL( ..... )
let task2 = session.DownloadTaskWithURL( ..... )
dict[task1] = 0
dict[task2] = 1
and in the delegate call, you can get the task correspond to number you set like this
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()
}
}
来源:https://stackoverflow.com/questions/31023785/how-can-i-download-datas-from-multiple-url-in-concurrency-mode