七天學會 swift - 在背景中下載資料並存檔 Day7


URLSession 可以設定在背景中下載檔案,但是除了只能使用 URLSessionDownloadTask 外,並且必須設定 delegate 而不能使用 block 來取得檔案路徑。

  • 步驟說明

    1. 建立 Single View App 專案
    2. 若為 http 網址,ATS 設定請參考附錄 D。
    3. 開啟 Main.storyboard,拖放一個 Image View 元件到 View Controller 上。
    4. 開啟 ViewController.swift,用藍線設定 Image View 元件的 IBOutlet 屬性,並且讓這個類別符合 URLSessionDownloadDelegate 協定的規範。

      class ViewController: UIViewController, URLSessionDownloadDelegate {
       @IBOutlet weak var imageView: UIImageView!
      
    5. 在 viewDidLoad() 中透過 URLSessionDownloadTask 下載圖片,並且設定可在背景執行。

      override func viewDidLoad() {
       super.viewDidLoad()
      
       let url = URL(string: "某圖片的網址")
       //使用者背景設定建立 session,並且給一個 session 的名字
       let config = URLSessionConfiguration.background(withIdentifier: "abc")
       // delegateQueue 如果為 nil,delegate 會在另外一個執行緒中被呼叫
       let session = URLSession(configuration: config, delegate: self,delegateQueue: nil)
       let dnTask = session.downloadTask(with: url!)
      
       dntask.resume()
      }
      

      如果參數 delegateQueue 填入 OperationQueue.main,則所有的 delegate 都會在主執行緒中執行。

    6. 這個函數會在檔案下載完成並且存檔後呼叫。所以我們在這個函數中透過存檔路徑開啟檔案,然後在 Image View 上顯示。

      func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
       if let data = try? Data(contentsOf: location) {
           DispatchQueue.main.async(execute: {
               self.imageView.image = UIImage(data: data)
           })
       }
      }
      
    7. 實作這個函數可以在下載完成後得知是否有錯誤產生

      func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
       if error == nil {
           print("下載成功")
       }else {
           print("下載失敗: \(error!)")
       }
      }
      
    8. 實作此函數可以當 APP 從背景變成前景時通知使用者下載已經完成。

      func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
       print("下載程式完成")
      }
      
    9. 這個函數可以得知目前下載進度,注意只有當 APP 在前景時才會被呼叫。

      func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData byteWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64) {
       //計算下載進度
       let progress = Float(totalBytesWritten) / Float(totalBytesExpectedToWrite)
       print("下載進度 \(progress)")
      }
      
    10. 執行結果

      下載進度 0.93537
      下載進度 1.0
      
#swift #iOS





這個系列將會帶大家入門 swift,內容上會較簡單,適合剛學習寫程式的新手

留言討論