博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
教你如何封装异步网络连接NSURLConnection实现带有百分比的下载
阅读量:6713 次
发布时间:2019-06-25

本文共 3433 字,大约阅读时间需要 11 分钟。

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

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

 

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

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

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

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

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

 

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

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

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

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

.......

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

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

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

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

以下是一份完整的代码:

#import 
// 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 ()
{ 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://mlolo.baihongyu.com/

你可能感兴趣的文章
ecshop标签
查看>>
阅读书籍---程序员必读系列
查看>>
C++中的单例模式
查看>>
数据库时间戳设计
查看>>
Retrofit2.0- 源码分析
查看>>
webpack笔记
查看>>
Android常用技能
查看>>
Spring Data JPA REST Query Criteria
查看>>
In FontFamilyFont, unable to find attribute android:font的报错处理
查看>>
网络编程-I/O基础
查看>>
Netty+SpringBoot+FastDFS+Html5实现聊天App详解(一)
查看>>
【跃迁之路】【721天】程序员高效学习方法论探索系列(实验阶段478-2019.2.11)...
查看>>
区块链之比特币的潜在激励
查看>>
Learning Python, 5th Edition 读书笔记 1
查看>>
【译】理解回调和Promise
查看>>
市场变冷,不要灰心。更应该延长你的黄金岁月
查看>>
又一轮子?Typescript+React+Redux,放弃saga,支持服务器渲染同构
查看>>
一起再看执行上下文/作用域链/原型链
查看>>
区块链是一种用一种不可变的形式存储数字信息
查看>>
【须弥SUMERU】宜信分布式安全服务编排实践
查看>>