Делегаты 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)
}
}
3 ответа
Из моего тестирования вы должны выбрать, хотите ли вы использовать делегат или обработчик завершения - если вы укажете оба, будет вызван только обработчик завершения. Этот код дал мне запущенные обновления прогресса и 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, NSURLSession API является очень асинхронным. Он возвращает данные одним из двух способов, в зависимости от методов, которые вы вызываете:
- В блок обработчика завершения, который возвращает данные в ваше приложение, когда передача завершается успешно или с ошибкой.
- Вызывая методы для вашего пользовательского делегата по мере получения данных.
- Вызывая методы вашего пользовательского делегата, когда загрузка в файл завершена.
Таким образом, по замыслу он возвращает данные либо в блок обработчика завершения, либо в делегат. Но, как показано здесь, не оба.
Интересно, что Apple специально объясняет это поведение в своихNSURLSessionDataDelegate
(но ни в базовом делегате NSURLSessionTaskDelegate
ни в NSURLSessionDownloadDelegate
)
НОТА
Объект NSURLSession не должен иметь делегата. Если делегат не назначен, при создании задач в этом сеансе необходимо предоставить блок обработчика завершения для получения данных.
Блок обработчика завершения предназначен в основном как альтернатива использованию пользовательского делегата. Если вы создаете задачу с использованием метода, который принимает блок обработчика завершения, методы делегата для ответа и доставки данных не вызываются.
Свифт 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")
}
}