2017-11-18 12 views
1

サーバーから画像をダウンロードし、アプリ内に表示する必要があります。私はURLSessionDownloadプロトコルを使用して、ダウンロードのステータスとすべてのプロセスの進行状況を取得します。これは私のコードです:URLSessionDownloadを使用して画像をダウンロードする方法は?

var downloadBGTask: URLSessionDownloadTask! 
var downloadBGSession: URLSession! 

override func viewDidLoad() { 
    super.viewDidLoad() 

    self.downloadBGSession = { 
     let downloadBGSessionConfig = URLSessionConfiguration.background(withIdentifier: "downloadBGSession") 
     return URLSession(configuration: downloadBGSessionConfig, delegate: self, delegateQueue: OperationQueue.main) 
    }() 

    self.downloadBGTask = self.downloadBGSession.downloadTask(with: "http.. ETC .png") 
    self.downloadBGTask.resume() 
} 

プロトコル

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64){ 
    self.loadingLabel.text = "Loading (\((Float(totalBytesWritten)/Float(totalBytesExpectedToWrite)) * 100)%)" 
} 

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
    print("Download Completed") 

    // How do I get the image I downloaded? 
    // This code below doesn't even compile 
    self.randomImg.image = UIImage(data: downloadTask.response!) 
} 

任意のアドバイスはありますか?

答えて

0

locationは、データの一時ファイルURLです。だから、あなたが行うことができます:あなたはそれを使用する前に、あなたも、キャッシュフォルダに保存可能性がある、

extension ViewController: URLSessionDownloadDelegate { 
    ... 

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
     print("Download Completed") 

     let data = try! Data(contentsOf: location) 
     randomImg.image = UIImage(data: data) 
    } 
} 

するか、(location内のファイルURLはできるだけ早くあなたが戻るように除去される一時ファイルのためであるため) :

/// Local file URL for cached image 

let cachedImageFileURL = try! FileManager.default 
    .url(for: .cachesDirectory, in: .userDomainMask, appropriateFor: nil, create: true) 
    .appendingPathComponent("saved.png") 

そして:

extension ViewController: URLSessionDownloadDelegate { 
    ... 

    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
     print("Download Completed") 

     imageDownloadInProgress = false 

     try! FileManager.default.copyItem(at: location, to: cachedImageFileURL) 
     let data = try! Data(contentsOf: location) 

     randomImg.image = UIImage(data: data) 
    } 

} 

しかしquestiあなたはなぜ背景をしているのですかURLSession。あなたがこれをやろうとするなら、あなたは他のことをする必要があります。たとえば、アプリのデリゲートは、アプリがバックグラウンド要求が完了したときに実行されていなかった場合の完了ハンドラをキャプチャする必要があります。

var backgroundRequestCompletionHandler: (() -> Void)? 

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping() -> Void) { 
    backgroundRequestCompletionHandler = completionHandler 
} 

そして、あなたのビューコントローラを(本当にURLSessionDelegateになるだろう場合)、呼び出す必要があります背景セッション要求の処理が行われ、この保存完了ハンドラ:

extension ViewController: URLSessionDelegate { 
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { 
     let appDelegate = UIApplication.shared.delegate as! AppDelegate 

     appDelegate.backgroundRequestCompletionHandler?() 
    } 
} 

しかし、あなたはこれをやっている場合は、ダウンロードが有してもよいようviewDidLoadは常に(新しいダウンロードを開始するために、それは意味がありません。アプリの以前の呼び出しによって既に開始されている)。したがって、ダウンロード要求を開始する前に、次のようにしてください:

  • 以前の要求からのキャッシュファイルの存在を探します。そして
  • 永続ストレージまたはURLSession非同期メソッドgetTasksWithCompletionHandler(_:)を使用して、この状態を保存有するか、ダウンロードが進行中であるかどうかを確認してください(。
+0

あなたは完全に右!私は無意味な何かをやっている!私の最初の目標をアニメーションが始まる前に画像をダウンロードして表示しようとしていましたが、接続が悪い(おそらくタイムアウトの場合)対処方法がわかりませんでした – user3582537

+0

@ user3582537 - バックグラウンドセッションの導入ははるかに複雑です。これらのメソッドでは 'Data'または' URL'が 'nil'ではないか、' Error'リファレンスが 'nil 'であるかどうかをチェックするだけです'しかし、うまくいけば私はあなたにダウンロードタスクのためにあなたに返される「URL」。 – Rob

+0

ありがとう!私はこの方法を選択しました。なぜなら、完了したdataTaskを使用したとき、それは「完了」ブロックと呼ばれましたが、ダウンロードされたイメージを表示する前に約2/3秒かかったからです。しかし、おそらく私は別の質問を投稿する必要があります。あなたの助けと忍耐ありがとう – user3582537

関連する問題