[Xcode10 实际操作]八、网络与多线程-(16)使用网址会话对象URLSession下载图片并显示下载进度

本文将演示如何通过网址会话对象URLSession显示下载图片的进度。

网址会话对象URLSession具有在后台上传和下载、暂停和恢复网络操作、丰富的代理模式等优点。

在项目导航区,打开视图控制器的代码文件【ViewController.swift】

  1 import UIKit
  2 
  3 //首先给当前的视图控制器类,添加一个下载代理协议,用来实时检测下载进度
  4 class ViewController: UIViewController, URLSessionDownloadDelegate {
  5     
  6     //创建两个视图,作为实时下载的进度条
  7     var backgroundView:UIView = UIView()
  8     var foregroundView:UIView = UIView()
  9     //创建一个标签对象,显示下载进度的百分比
 10     var progressLabel:UILabel = UILabel()
 11     
 12     override func viewDidLoad() {
 13         super.viewDidLoad()
 14         // Do any additional setup after loading the view, typically from a nib.
 15         
 16         //对进度条视图的进行样式设置
 17         //设置进度条的背景视图位于(16,106),尺寸为(288,44)
 18         backgroundView.frame = CGRect(x: 16, y: 106, width: 288, height: 44)
 19         //设置进度条的背景视图的背景颜色为浅灰色
 20         backgroundView.backgroundColor = UIColor.lightGray
 21         
 22         //设置进度条的前景视图位于(20,110),尺寸为(0,36),
 23         //它的初始宽度为0 ,当图片下载时,根据下载的进度,调整图片的宽度
 24         foregroundView.frame = CGRect(x: 20, y: 110, width: 0, height: 36)
 25         //设置进度条的前景视图的背景颜色为绿色
 26         foregroundView.backgroundColor = UIColor.green
 27         
 28         //设置标签对象的位置在(20,160),尺寸为(280,36),
 29         progressLabel.frame = CGRect(x: 20, y: 160, width: 280, height: 36)
 30          //设置标签对象的文字对齐方式设置为居中对齐
 31         progressLabel.textAlignment = NSTextAlignment.center
 32         
 33         //将背景视图添加到当前视图控制器的根视图
 34         self.view.addSubview(backgroundView)
 35         //将前景视图添加到当前视图控制器的根视图
 36         self.view.addSubview(foregroundView)
 37         //将标签对象添加到当前视图控制器的根视图
 38         self.view.addSubview(progressLabel)
 39         
 40         //创建一个网址对象,指定请求网络图片的地址
 41         let url = URL(string: "https://www.cnblogs.com/strengthen/images/logo.png")
 42         //创建一个网络请求对象
 43         let request:URLRequest = URLRequest(url: url!)
 44         
 45         //网址会话URLSession在2013年发布,苹果对它的定位是作为旧的网络请求接口的替代者。
 46         //这里获得网址会话的单例对象,生成单例对象的方法buildSession()在下文实现
 47         let urlSession = self.buildSession() as Foundation.URLSession
 48         //创建一个执行下载操作的网络请求任务
 49         let task = urlSession.downloadTask(with: request)
 50         //任务创建后,调用resume方法开始工作
 51         task.resume()
 52     }
 53     
 54     //添加一个方法,用来生成网址会话对象
 55     func buildSession() -> Foundation.URLSession
 56     {
 57         //创建一个网址会话对象
 58         var session:URLSession? = nil
 59         
 60         //获得网址会话配置的单例对象
 61         let config = URLSessionConfiguration.default
 62         
 63         //通过网址会话配置对象,创建一个网址会话对象,
 64         //并设置对象的代理为当前视图控制器对象
 65         session = URLSession(configuration: config, delegate: self, delegateQueue: nil)
 66         //返回设置好的网址会话对象
 67         return session!
 68     }
 69     
 70     //添加一个代理方法,用来响应下载任务完成后的的动作
 71     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,didFinishDownloadingTo location: URL)
 72     {
 73         //创建一个异常捕捉语句,用来执行图片下载后的移动操作
 74         do
 75         {
 76             //获得网络下载后,位于缓存目录的,图片原始存储路径
 77             let originalPath = location.path
 78             //并在控制台打印输出原始存储路径
 79             print("Original location:\(originalPath)")
 80             
 81             //创建一个字符串,作为图片存储的目标位置
 82             let targetPath:String = NSHomeDirectory() + "/Documents/logo.png"
 83             
 84             //获得文件管理对象,它的主要功能包括:
 85             //1.读取文件中的数据
 86             //2.向文件中写入数据
 87             //3.删除或复制文件
 88             //4.移动文件
 89             //5.比较两个文件的内容
 90             //6.测试文件的存在性
 91             let fileManager:FileManager = FileManager.default
 92             //判断目标位置的文件是否已经存在,如果不存在,则进行移动操作
 93             if !fileManager.fileExists(atPath: targetPath)
 94             {
 95                 //将下载后的图片,从原始位置,移动到目标位置
 96                 try fileManager.moveItem(atPath: originalPath, toPath: targetPath)
 97                 //在控制台打印输出图片存储后的位置
 98                 print("new location:\(targetPath)")
 99             }
100         }
101         catch
102         {
103             print("Network error.")
104         }
105     }
106     
107     //创建一个代理方法,用来响应下载任务的进度变化
108     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)
109     {
110         //计算已经从网络下载的数据量,
111         //与总共需要下载的数据量的比值。
112         let rate:CGFloat = CGFloat(totalBytesWritten)/CGFloat(totalBytesExpectedToWrite)
113         
114         //从一个分离的线程,切换至主线程,以进行界面的改动
115         DispatchQueue.main.async(execute: { () in
116             //利用各个得到的比值,更新进度条前景视图的宽度
117             self.foregroundView.frame.size.width = rate * 280
118             //如果数据全部下载完成,
119             if rate == 1.0
120             {
121                 //设置标签对象的文字内容,提示用户下载成功
122                 self.progressLabel.text = "Finished !!!"
123             }
124         })
125     }
126     
127     //添加一个代理方法,响应任务恢复的事件,
128     func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask,didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64)
129     {
130         print(fileOffset)
131     }
132     
133     override func didReceiveMemoryWarning() {
134         super.didReceiveMemoryWarning()
135         // Dispose of any resources that can be recreated.
136     }
137 }

猜你喜欢

转载自www.cnblogs.com/strengthen/p/10062166.html
今日推荐