2014-11-02 11 views
14

Nel seguente codice, il file viene scaricato correttamente. Tuttavia nessuno dei metodi delegati sembra essere chiamato in quanto non ricevo output di sorta. neanche il progressView non è aggiornato. Qualche idea del perché?NSURLSession delegati non chiamati

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

Prova a passare [NSOperationQueue mainQueue] invece pari a zero al parametro delegateQueue – rdelmar

risposta

21

Dal mio test, è necessario scegliere se si desidera utilizzare un delegato o di un gestore di completamento - se si specifica entrambi, solo il gestore di completamento viene chiamato. Questo codice mi ha dato esecuzione aggiornamenti sullo stato di avanzamento e l'evento 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) 
} 

Dal NSURLSession documentation, ecco la sezione pertinente:

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.

Così da un design che restituisce i dati a sia un completamento handler block o un delegato. Ma come è stato dimostrato qui, non entrambi.

+0

I' Non sono sicuro che sia corretto, altrimenti sarebbe un orrendo design API. Inoltre, date un'occhiata a AFNetworking, AFURLSessionManager basa tutto il design sui callback dei delegati, ma è ancora possibile creare richieste con i gestori di completamento ... –

+0

Potrebbe essere un'orribile progettazione dell'API, o forse un bug, poiché il comportamento non è documentato. AFNetworking precede 'NSURLSession' - è basato su' NSURLConnection', che 'NSURLSession' intende sostituire. In ogni caso, persistere l'oggetto della sessione non risolve il problema. –

+0

@DanielGalasko Trovato in fondo alla documentazione - vedi aggiornamento. –

12

interessante, Apple specifically explains this behavior in their NSURLSessionDataDelegate (ma né nel delegato di base NSURLSessionTaskDelegateNSURLSessionDownloadDelegate)

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

wow, questo dovrebbe essere evidenziato. grazie. – 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") 
    } 
} 
Problemi correlati