zoukankan      html  css  js  c++  java
  • 教你如何封装异步网络连接NSURLConnection实现带有百分比的下载

    教你如何封装异步网络连接NSURLConnection实现带有百分比的下载

    注:本教程需要你对block有着较为深刻的理解,且对如何封装对象有着一些经验.

    也许你已经用惯了AFNetworking2.0,或者是ASIHTTPRequest(这个已经都不更新了,还不支持ARC,放弃为妙^_^),或者还有其他轻量级的开源代码.用着是很爽,但有时候我们只想实现简单的功能,用不着那么复杂,而且,那些开源代码太多,我们很难理解,那就尝试一下自己封装一个简单的吧.

    NSURLConnection有着两种类型的实现,一种是同步的:

    使用非常简单,它直接根据request返回一个data给你,不过因为是同步的,会阻塞主线程,你可以将他放到线程中就能把它变成异步的了,很easy,自己尝试.

    剩下的几种基本上都是异步的了,实现起来也很容易,继承几个协议实现几个方法而已嘛.

    上面的这么多操作,你只完成了一个功能,那就是下载一张图片而已.

    如果我们能把一个网络地址链接抽象成一个对象,而这个对象来处理所有的这些操作,不需要我们把它暴露出来,比如像下面的使用方式:

    某某类   *对象1 = [初始化一个网址];

    [对象1 开始执行网络请求];

    [对象1 监测下载状况];

    .......

    像上面的使用方式,非常接近人的思维方式,给链接地址,开始下载,监控下载状况,我们就应该这么用嘛.

    那我们就按照这种套路来设计我们的类了.

    能初始化一个网址以及有一个开始操作:

    如何才能够不用协议就可以获取到下载进度呢(监测下载状态),我们就用block当做属性来获取下载进度:

    以下是一份完整的代码:

    #import <Foundation/Foundation.h>
    
    // block的相关定义
    typedef void (^downloadProgressBlock_t)
    (NSData *data, long long totalBytesReceived, long long totalBytesExpectedToReceive);
    typedef void (^completionDataBlock_t)(NSDictionary *headers, NSData *body);
    
    @interface YXNetwork : NSObject
    
    // 将block定义成属性
    @property (nonatomic, copy) downloadProgressBlock_t  downloadProgressBlock;
    @property (nonatomic, copy) completionDataBlock_t    completionDataBlock;
    
    // 初始化方法
    - (instancetype)initWithUrlString:(NSString *)urlString;
    
    // 开始网络下载
    - (void)start;
    
    @end

    要下载东西我们需要能够存储数据,因为是下载,肯定也需要有网络链接,我们还需要知道下载数据期望的最大数值,要不然我们怎么表示进度呢?

    基本思路就是这样子的,我们开始写代码了:

    #import "YXNetwork.h"
    
    @interface YXNetwork ()<NSURLConnectionDelegate, NSURLConnectionDataDelegate>
    
    {
        long long  _expectedLength;                                 // 期望最大的数据长度
    }
    
    @property (nonatomic, strong) NSMutableData   *storeData;       // 存储下载的数据
    @property (nonatomic, strong) NSURLConnection *dataConncetion;  // 网络链接对象
    @property (nonatomic, strong) NSDictionary    *responseHeaders; // 该网络链接所有头信息
    
    @end
    
    
    @implementation YXNetwork
    
    - (instancetype)initWithUrlString:(NSString *)urlString
    {
        self = [super init];
        if (self)
        {
            self.storeData = [NSMutableData new];
            self.dataConncetion = 
            [[NSURLConnection alloc] initWithRequest:netURLRequest(urlString)
                                            delegate:self
                                    startImmediately:NO];
        }
        
        return self;
    }
    
    - (void)start
    {
        [self.dataConncetion start];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        if([response isKindOfClass:[NSHTTPURLResponse class]])
        {
            NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
            
            // 如果能获取到期望的数据长度就执行括号中的方法
            if ([r expectedContentLength] != NSURLResponseUnknownLength)
            {
                _expectedLength  = [r expectedContentLength];
                _responseHeaders = [r allHeaderFields];
            }
            else
            {
                _expectedLength = 0;
            }
        }
        
        // 设置长度为0
        [_storeData setLength:0];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)theData
    {
        [_storeData appendData:theData];
        
        // 如果指定了block
        if (_downloadProgressBlock)
        {
            _downloadProgressBlock(theData, [_storeData length], _expectedLength);
        }
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
        // 如果指定了block
        if (_completionDataBlock)
        {
            _completionDataBlock(_responseHeaders, _storeData);
        }
    }
    
    NS_INLINE NSURLRequest *netURLRequest(NSString *netPath)
    {
        //创建简单的网络请求
        return [NSURLRequest requestWithURL:[NSURL URLWithString:netPath]];
    }
    
    @end

    代码很简单,需要你对block有一定的了解,你拷贝如上两段代码到你的工程文件中,可以看看是怎么实现的.

    现在来看看怎么使用:

    比你之前直接用系统的那个NSURLConnection清爽了很多很多倍,对吧.

    以下是下载图片时运行的截图:

    给你提供高清图片下载地址: http://wallpapers.wallbase.cc/high-resolution/wallpaper-2594485.jpg

    只要你愿意,你想怎么封装就怎么封装,就是这么简单,自己动手,丰衣足食^_^.

  • 相关阅读:
    git 基础操作 && 在"develop"分支修改动但不想提交切换到"master"分支(最后)
    html、css面试题 持续更新中......
    JS面试题 持续更新中......
    盒子模型
    Tomcat环境设置及第一个JSP程序实现
    嵌入式V3s交叉编译 tslib和QT4.8.7,并使用Qt Creator编译项目
    嵌入式全志V3s荔枝派板卡移植 aircrack-ng
    为嵌入式全志V3s荔枝派板卡添加USB MT7601U(小米随身WIFI)驱动
    为嵌入式mplayer移植添加ALSA音频驱动(全志V3s荔枝派zero)
    Makefile知识点总结
  • 原文地址:https://www.cnblogs.com/YouXianMing/p/3708868.html
Copyright © 2011-2022 走看看