Делегаты NSURLSession не вызывают
В следующем коде файл загружается просто отлично. Однако ни один из методов делегата, как представляется, не называется, поскольку я не получаю никакого вывода. progressView также не обновляется. Любая идея почему?
import Foundation
import UIKit
class Podcast: PFQueryTableViewController, UINavigationControllerDelegate, MWFeedParserDelegate, UITableViewDataSource, NSURLSessionDelegate, NSURLSessionDownloadDelegate {
func downloadEpisodeWithFeedItem(episodeURL: NSURL) {
var request: NSURLRequest = NSURLRequest(URL: episodeURL)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: nil)
var downloadTask = session.downloadTaskWithURL(episodeURL, completionHandler: { (url, response, error) -> Void in
println("task completed")
if (error != nil) {
println(error.localizedDescription)
} else {
println("no error")
println(response)
}
})
downloadTask.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
println("didResumeAtOffset")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
var downloadProgress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
println(Float(downloadProgress))
println("sup")
epCell.progressView.progress = Float(downloadProgress)
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println(location)
}
}
Ответы
Ответ 1
Из моего тестирования вы должны выбрать, хотите ли вы использовать делегат или обработчик завершения - если вы укажете оба, вызывается только обработчик завершения. Этот код дал мне текущие обновления и событие didFinishDownloadingToURL
:
func downloadEpisodeWithFeedItem(episodeURL: NSURL) {
let request: NSURLRequest = NSURLRequest(URL: episodeURL)
let config = NSURLSessionConfiguration.defaultSessionConfiguration()
let session = NSURLSession(configuration: config, delegate: self, delegateQueue: NSOperationQueue.mainQueue())
let downloadTask = session.downloadTaskWithURL(episodeURL)
downloadTask.resume()
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64) {
println("didResumeAtOffset: \(fileOffset)")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
var downloadProgress = Double(totalBytesWritten) / Double(totalBytesExpectedToWrite)
println("downloadProgress: \(downloadProgress)")
}
func URLSession(session: NSURLSession, downloadTask: NSURLSessionDownloadTask, didFinishDownloadingToURL location: NSURL) {
println("didFinishDownloadingToURL: \(location)")
println(downloadTask)
}
Из NSURLSession
документации, здесь соответствующий раздел:
Как и большинство сетевых API, API NSURLSession отличается высокой асинхронностью. Он возвращает данные одним из двух способов, в зависимости от методов, которые вы вызываете:
- К блоку обработчика завершения, который возвращает данные в ваше приложение, когда передача завершается успешно или с ошибкой.
- Вызов методов в пользовательском делетете при получении данных.
- Вызов методов вашего пользовательского делегата при завершении загрузки в файл.
Поэтому по дизайну он возвращает данные в либо блок обработчика завершения или делегата. Но, как показано здесь, не оба.
Ответ 2
Интересно, что Apple конкретно объясняет это поведение в своем NSURLSessionDataDelegate
(но ни в базовом делетете NSURLSessionTaskDelegate
, ни в NSURLSessionDownloadDelegate
),
Примечание
Объект NSURLSession не должен иметь делегата. Если делегат не назначен, при создании задач в этом сеансе вы должны предоставить блок обработчика завершения для получения данных.
Блок обработчика завершения в первую очередь предназначен как альтернатива использованию пользовательского делегата. Если вы создаете задачу с использованием метода, который принимает блок обработчика завершения, методы делегата для ответа и доставки данных не вызываются.
Ответ 3
Swift 3
class ViewController: UIViewController {
var urlLink: URL!
var defaultSession: URLSession!
var downloadTask: URLSessionDownloadTask!
}
// MARK: Button Pressed
@IBAction func btnDownloadPressed(_ sender: UIButton) {
let urlLink1 = URL.init(string: "https://github.com/VivekVithlani/QRCodeReader/archive/master.zip")
startDownloading(url: urlLink!)
}
@IBAction func btnResumePressed(_ sender: UIButton) {
downloadTask.resume()
}
@IBAction func btnStopPressed(_ sender: UIButton) {
downloadTask.cancel()
}
@IBAction func btnPausePressed(_ sender: UIButton) {
downloadTask.suspend()
}
func startDownloading (url:URL) {
let backgroundSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "backgroundSession")
defaultSession = Foundation.URLSession(configuration: backgroundSessionConfiguration, delegate: self, delegateQueue: OperationQueue.main)
downloadProgress.setProgress(0.0, animated: false)
downloadTask = defaultSession.downloadTask(with: urlLink)
downloadTask.resume()
}
// MARK:- URLSessionDownloadDelegate
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
print("File download succesfully")
}
func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
downloadProgress.setProgress(Float(totalBytesWritten)/Float(totalBytesExpectedToWrite), animated: true)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
downloadTask = nil
downloadProgress.setProgress(0.0, animated: true)
if (error != nil) {
print("didCompleteWithError \(error?.localizedDescription)")
}
else {
print("The task finished successfully")
}
}