我需要从服务器下载图像并在我的应用程序中显示它。我选择使用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 :(得分: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)
}
}
或者,您也可以在使用它之前将其保存到caches文件夹中(因为URL
中的文件location
用于临时文件,一旦返回就会被删除):
/// 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)
}
}
但问题是你为什么要做背景URLSession
。如果您要这样做,您必须做其他事情。例如,如果应用程序在后台请求完成时未运行,则app delegate必须捕获完成处理程序:
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(_:)
。