2014-11-02 98 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 2014-11-02 00:23:59

回答

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」我不確定這是否正確,否則這將是可怕的API設計。此外,看看AFNetworking,AFURLSessionManager基於委託回調的所有設計,但您仍然可以使用完成處理程序創建請求... – 2014-11-02 09:36:29

+0

這可能是可怕的API設計,也可能是一個錯誤,因爲行爲沒有記錄。 AFNetworking早於NSURLSession,它基於NSURLConnection,NSURLSession是用來替代的。在任何情況下,持久化會話對象都不能解決問題。 – 2014-11-02 15:59:42

+0

@DanielGalasko畢竟在文檔中發現它 - 請參閱更新。 – 2014-11-03 02:13:09

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 2017-12-11 13:20:27

2

夫特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") 
    } 
}