2014-11-02 2 views
14

В следующем коде файл загружается просто отлично. Однако ни один из методов делегата, как представляется, не называется, поскольку я не получаю никакого вывода. progressView также не обновляется. Любая идея почему?NSURLSession делегаты не вызываются

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) 

} 
} 
+0

Попытка прохождения [NSOperationQueue mainQueue] вместо нуля параметру delegateQueue – rdelmar

ответ

21

Из моего тестирования, вы должны выбрать, хотите ли вы использовать делегат или обработчик завершения - если вы укажете как только обработчик завершения вызывается. Этот код дал мне запуск обновления прогресса и 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 documentation, вот соответствующий раздела:

Like most networking APIs, the NSURLSession API is highly asynchronous. It returns data in one of two ways, depending on the methods you call:

  • To a completion handler block that returns data to your app when a transfer finishes successfully or with an error.
  • By calling methods on your custom delegate as the data is received.
  • By calling methods on your custom delegate when download to a file is complete.

Итак, дизайн возвращает данные в либо пополнении блок обработчика или делегат. Но, как показали здесь, не оба.

+0

I» m не уверен, что это правильно, в противном случае это был бы ужасный дизайн API. Кроме того, взгляните на AFNetworking, AFURLSessionManager основывает весь дизайн на обратных вызовах делегатов, но вы все равно можете создавать запросы с обработчиками завершения ... –

+0

Это может быть ужасный дизайн API или, возможно, ошибка, поскольку поведение недокументировано. AFNetworking предшествует «NSURLSession» - он основан на «NSURLConnection», который «NSURLSession» предназначен для замены. В любом случае, сохранение объекта сеанса не устраняет поведение. –

+0

@ DanielGalasko В конце концов, это было в документах - см. Обновление. –

12

Интересно, что Apple specifically explains this behavior in their NSURLSessionDataDelegate (но ни в базовом делегата NSURLSessionTaskDelegate, ни в NSURLSessionDownloadDelegate)

NOTE

An NSURLSession object need not have a delegate. If no delegate is assigned, when you create tasks in that session, you must provide a completion handler block to obtain the data.

Completion handler block are primarily intended as an alternative to using a custom delegate. If you create a task using a method that takes a completion handler block, the delegate methods for response and data delivery are not called.

+0

Вау, это должно быть выделено. Спасибо. – user1974368

2

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") 
    } 
} 
Смежные вопросы