swift 网络----利用URLSession的Data Task下载单张图片(包含图片的增量下载)

一、说明

NSURLSession是OC中的会话类,在Swift中变成URLSession类,它们的实现方式是一样的,下面的示例就Swift语法进行讲解和介绍。

二、介绍:

URLSession 类支持3种类型的任务:加载数据、下载和上传。

加载数据:Data Task

下载数据:Downlaod Task

上传数据:Upload Task

毫无疑问,Session Task是整个URLSession架构的核心目标。

三。  加载数据:Data Task

1. URLSession的URLSessionDataDelegate模式下载网络封装 (包含图片的增量下载)

import Foundation
import UIKit

public typealias SwiftClosure = ((_ data:Data? , _ progressValue:Float, _ error: Error?) -> Void)

class LJSessionRequestManager: NSObject{
    
    /**
     *  定义闭包属性,可选类型
     */
    public  var callBackClosure : SwiftClosure?

    func sessoinDownload(_ url: String, _ method : String , _ callback: @escaping SwiftClosure)
    {
        callBackClosure = callback
        
        //1、创建URL下载地址
        let url:URL! = URL(string:url);
        
        //2、创建Request对象
        var urlRequest:URLRequest = URLRequest(url:url);
        urlRequest.httpMethod = method
        
        //不需要缓存
        urlRequest.cachePolicy = .reloadIgnoringLocalCacheData
        
        //3、创建会话
        let config = URLSessionConfiguration.default
        let session  = URLSession(configuration: config, delegate:self, delegateQueue: nil)

        //4、下载任务  -- URLSessionDataDelegate 模式
        let loadDataTask = session.dataTask(with: urlRequest)
        
        //5、启动任务
        loadDataTask.resume()
    }
    
    //初始化一个data,用来存储下载下来的数据
    private var _responseData: NSMutableData!
    var responseData: NSMutableData!{
        get{
            if _responseData == nil {
                _responseData = NSMutableData()
            }
            return _responseData
        }
        set{
            self._responseData = newValue
        }
    }
}

extension LJSessionRequestManager:URLSessionDataDelegate
{
    @available(iOS 7.0, *)
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Swift.Void)
    {
        //允许继续加载数据
        completionHandler(.allow)
    }
    
    @available(iOS 7.0, *)
    func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
    {
        //每次获取的data在此拼装
        print("Data......\(data)")
        self.responseData.append(data)
        
        let  currentBytes :Float = Float(self.responseData.length)
        let  allTotalBytes :Float = Float((dataTask.response?.expectedContentLength)!)
        
        let proValu :Float = Float(currentBytes/allTotalBytes)
        print("----下载进度:------\(proValu*100)%");
        
        if callBackClosure != nil ,((dataTask.response?.expectedContentLength) != nil)
        {
            //避免循环引用,weak当对象销毁的时候,对象会被指定为nil
            //weak var weakSelf = self //对象推到,省略了ViewController
            weak var weakSelf : LJSessionRequestManager? = self  //等同与上面的表达式
            
            DispatchQueue.main.async
                {
                    //将接收的数据结果回调到前台,用于进度展示,动态展示下载的图片
                    weakSelf?.callBackClosure!(self.responseData as Data,proValu ,nil)
                }
        }
    }
    
     func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?)
    {
        if callBackClosure != nil ,let data = self.responseData{
            
            weak var weakSelf : LJSessionRequestManager? = self
            DispatchQueue.main.async
            {
                    print("数据下载完毕")
                    //将接收的数据结果回调到前台,用于进度展示
                    weakSelf?.callBackClosure!(data as Data ,1.0 ,nil)
            }
        }

    }
}


2. 下面demo界面(包含下载进度条)
import Foundation
import UIKit

class LJNetImageViewController: TFBaseViewController {
    
    var progressView : UIProgressView?
    var progressValue : Float = 0.0
    var ljImageView : UIImageView?
    var ljDownLoadManage : LJSessionRequestManager?
    
    var imageUrlArray = ["https://raw.githubusercontent.com/onevcat/Kingfisher/master/images/kingfisher-\(/*indexPath.row +*/ 2).jpg",
        "http://image.nationalgeographic.com.cn/2015/0121/20150121033625957.jpg",
        "http://image.nationalgeographic.com.cn/2017/0703/20170703042329843.jpg",
        "http://image.nationalgeographic.com.cn/2017/0702/20170702124619643.jpg",
        "http://image.nationalgeographic.com.cn/2017/0702/20170702124619643.jpg"]
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        self.setTopNavBarTitle("图片下载")
        self.setTopNavBackButton()
        
        self.createDownLoadBtn()
        self.createProgessView()
        self.createImageView()
        
    }
    
//MARK: --  UI
    func createDownLoadBtn() {
        let downLoadBtn = UIButton(frame: CGRect(x: (SCREEN_WIDTH - 100)/2.0, y: 120, width: 100, height: 40))
        downLoadBtn .setTitle("down load", for: UIControlState())
        downLoadBtn .addTarget(self, action: #selector(LJNetImageViewController.btnClicked(_:)), for: UIControlEvents.touchUpInside)
        downLoadBtn.backgroundColor = UIColor.gray
        self.view.addSubview(downLoadBtn)
    }
//MARK: 进度条
    func createProgessView() {
        progressView = UIProgressView.init(progressViewStyle: .default)
        progressView?.frame = CGRect(x: 0, y: 65, width: SCREEN_WIDTH, height: 1)
        progressView?.progressTintColor = UIColor.red
        progressView?.trackTintColor = UIColor.black
        self.view.addSubview(progressView!)
    }
    
    func createImageView(){
        ljImageView = UIImageView(frame: CGRect(x: (SCREEN_WIDTH - 200)/2.0, y: 180, width: 200, height: 200))
        self.view.addSubview(ljImageView!)
    }
    
    func loadNetImage() {
        ljDownLoadManage = LJSessionRequestManager()
        ljDownLoadManage?.sessoinDownload(imageUrlArray[1], "GET", { (data, progressValue ,error) in
            
            //避免循环引用,weak当对象销毁的时候,对象会被指定为nil
            //weak var weakSelf = self //对象推到,省略了ViewController
            weak var weakSelf : LJNetImageViewController? = self  //等同与上面的表达式
            DispatchQueue.main.async {
                weakSelf?.progressView?.setProgress(progressValue, animated: true)
                print("------进度打印:\(progressValue)")
                
                if error == nil, data != nil{
                    let image = UIImage(data: data!)
                    weakSelf?.ljImageView?.image = image
                }
            }
        })
    }

    func btnClicked(_ sender: UIButton)
    {
        //progressValue = progressValue + 0.1
        //progressView?.setProgress(progressValue, animated: true)
        
        self.loadNetImage()
    }
}


控制台打印数据

Data......5544 bytes

----下载进度:------97.1827%

------进度打印:0.933892

Data......1386 bytes

----下载进度:------97.815%

------进度打印:0.940215

Data......1386 bytes

----下载进度:------98.4472%

------进度打印:0.946537

Data......2772 bytes

----下载进度:------99.7117%

Data......632 bytes

----下载进度:------100.0%

------进度打印:0.971827

------进度打印:0.97815

------进度打印:0.984472

数据下载完毕

------进度打印:0.997117

------进度打印:1.0


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值