网络服务几乎是每一款成功APP的必备条件,打开你手机你会发现里面不用联网的应用数量十只手指可以数出来,就算是一些以独特技术切入市场的APP如美颜相机,都至少加入了分享功能。下面我先做下简单的回顾兼扫盲。

  苹果定义了NSConnection 这个类来专门处理网络请求,并且这个类有两种用法来满足开发者需求。

用法一,同步请求  

 //NSURLConnection.h
 @interface NSURLConnection (NSURLConnectionSynchronousLoading)
  + (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
 @end
//**.m
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:response error:error];

这种用法比较少人使用,因为他无法捕捉传输过程的内容,并且需要在子线程中使用,不然将会卡住主线程的UI绘制,直到sendSynchronousRequest返回data,但胜在简单易用,一目了然。

用法二,异步请求  

//NSURLConnection.h

 @interface NSURLConnection : NSObject

 - (instancetype)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSString *)mode;
- (void)start;
@end
//**.m
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];
NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[connection scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
[connection start];

相比第一种用法,第二种顿时让人云里雾里,特别nsrunloop更让人疑问,另外,上面的代码仅仅是开始请求部分,数据接收部分的代码还没贴出来。

细心的人注意到,在.m文件中,NSConnection初始化时传入了一个delegate,是的,数据便是通过NSURLConnectionDataDelegate的回调来处理的。

//NSURLConnection.h
@protocol NSURLConnectionDataDelegate <NSURLConnectionDelegate>
@optional
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
@end

为了不让其他函数扰乱了大家的实现,这里我只贴出跟本文有关的函数,从字面上大家都能知道这他们的作用了,didReceiveData会携带着请求下来的数据data多次回调,didFinishLoading是在请求结束后调用,另外还有一个didFailWithError在请求失败是调用,只不错他是老爸NSURLConnectionDelegate的内容。

下面我们回到第二种用法的.m文件,这里面涉及到runloop的执行机制,我在这里只解释为什么要这样设置。

Runloop有五种运行模式,这里我只说三种:

1,NSDefaultRunLoopMode: 默认的运行模式,除了NSConnection对象的事件;

2,UITrackingRunLoopMode: 用于跟踪触摸事件触发的模式(例如UIScrollView上下滚动),主线程当触摸事件触发时会设置为这个模式;

3,NSRunLoopCommonModes: 是一组常用的模式集合,简单来将就是模式集合,既然是集合,当然包括上面的两种模式。

默认情况下NSURLConnection,NSTimer都是运行1模式下,那么问题来了,假如这个时候用户刷一下屏幕,此时切换为模式2,而这时候刚好有数据请求下来,那么就悲剧了,didReceiveData不会回调。(如果NSTimer涉及精密的数据计算,这里也要注意下)解决办法就是替换成NSRunLoopCommonModes。

著名的SDWebImage在网络异步请求图片时也是使用第二种方法,个人觉得这种方法相当高效,在不创建新线程的情况下,依靠runloop来监听网络请求数据,如果同学们还是有点凌乱,不妨试下将NSURLConnection替换成NSTimer这样,其实原理都差不多。

另外这里有一点NSConnection在初始化的时候要注意startImmediately:不能设置为YES,如果你设置为YES,后在设置runloopmode是无效的。

现在理解了网络请求最具高效的方案(个人认为。。。),有没有感觉这些代理什么挺繁琐的,而一个APP不可能只有一个网络请求接口,这时候我们就需要一个管理者的角色,我们暂时将它命名为HttpManager。一个manager统领着一群connection,这时候你发现问题又来了,connection从外表上看长得都一样,没有可以标记的东西,于是,我们给他造个子类MyURLConnection 并且加多一个tag字段,来互相辨认。如图:

有了tag后,tag用什么来装填好呢,对tag唯一的要求就是不重复,这里我就直接使用url来做tag,因为除非奇葩需求,否侧url重复请求确实没有必要。

在didReceivaData中,_dataTagMap跟据tag,追加数据;

在sendHttpRequestWithUrl中,先检查_connectionTagMap中是否已经有以该url为key的对象了,有就说明已经这条请求,这条请求可以丢弃了。没有就new一个MyURLConnection 并将url作为tag,最后以url为key ,myconnection为value填入_connectionTagMap中;

在didFinishLoading中,根据connect的tag值,将对应的connection从_dataTagMap中提出来并发给对应的Model层处理,并从_dataTagMap和_connectionTagMap移除相应项;

好像听起来很简单的样子,实际上,也很简单。。。这里的发给Model层可能有些同学有迷糊了,什么叫发?大家注意到前面_connectionTagMap如果发现有重复直接丢弃即return,所以这要求HttpManager和与之交互的类必须低耦合,所以这里的发意思是指使用通知

 [[NSNotificationCenter defaultCenter] postNotificationName:KHTTPMgrNotificationSendRequestCompleted object:self userInfo:info];

info其实就一个NSDictionary,里面你想装什么就装什么,用过都知道。

今天先到这里吧,本来想写两种请求框架对比,结果只写了一种也只写了一半,只好下周末再补上对应的网络业务Model层以及另外一种请求框架了。

iOS WebServiceFramework网络服务框架浅解的更多相关文章

  1. iOS 开发之照片框架详解(2)

    一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...

  2. iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)

    本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...

  3. iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...

  4. iOS 开发之照片框架详解

    转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework.html 一. 概要 在 iOS 设备中,照片和视频是相当重 ...

  5. greenev —— Python 异步网络服务框架

    greenev是一个基于greenlet协程,事件驱动,非阻塞socket模型的Python网络服务框架,它使得可以编写同步的代码,却得到异步执行的优点. 本项目受到gevent, openresty ...

  6. [apue] 一个工业级、跨平台的 tcp 网络服务框架:gevent

    作为公司的公共产品,经常有这样的需求:就是新建一个本地服务,产品线作为客户端通过 tcp 接入本地服务,来获取想要的业务能力. 与印象中动辄处理成千上万连接的 tcp 网络服务不同,这个本地服务是跑在 ...

  7. 一个工业级、跨平台、轻量级的 tcp 网络服务框架:gevent

    前言 作为公司的公共产品,经常有这样的需求:就是新建一个本地服务,产品线作为客户端通过 tcp 接入本地服务,来获取想要的业务能力.与印象中动辄处理成千上万连接的 tcp 网络服务不同,这个本地服务是 ...

  8. iOS 开发之照片框架详解(1)

    http://kayosite.com/ios-development-and-detail-of-photo-framework.html/comment-page-1 一. 概要 在 iOS 设备 ...

  9. iOS 开发之照片框架详解(3)

    http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 三. 常用方法的封装 虽然 Phot ...

随机推荐

  1. python 字符串换行的三种方式

    if __name__ == '__main__': #第一种: 三个单引号 print ''' aaaaaaaaaaaaaaaa         bbbbbbbbbbbbbb''' #第二种: 三个 ...

  2. jQuery EasyUI - Add link to datagrid cell

    Extracted from: http://stackoverflow.com/questions/16061894/jquery-easyui-add-link-to-cell HTML: < ...

  3. Mybatis的if test字符串比较问题

    1. Mybatis判断字符串是否为空的变态写法 <if test="bussSceneIsNull =='0'.toString() "> <![CDATA[ ...

  4. servlet基础讲解

    基本知识一.Web结构1.两种应用程序 ①桌面应用程序:QQ.CS.MyEclipse.Office.DW.360.浏览器等必须下载.安装.桌面快捷方式.注册表信息.操作系统后台服务.占用操作系统端口 ...

  5. ScaleGestureDetector缩放view

    public class ScaleGesture implements OnScaleGestureListener { private float beforeFactor; private fl ...

  6. LA 4119 (差分数列 多项式) Always an integer

    题意: 给出一个形如(P)/D的多项式,其中P是n的整系数多项式,D为整数. 问是否对于所有的正整数n,该多项式的值都是整数. 分析: 可以用数学归纳法证明,若P(n)是k次多项式,则P(n+1) - ...

  7. Web网站的性能测试工具

    随着Web 2.0技术的迅速发展,许多公司都开发了一些基于Web的网站服务,通常在设计开发Web应用系统的时候很难模拟出大量用户同时访问系统的实际情况,因此,当Web网站遇到访问高峰时,容易发生服务器 ...

  8. Java Web编程的主要组件技术——Struts的高级功能

    参考书籍:<J2EE开源编程精要15讲> Struts对国际化的支持 "国际化"(I18N)指一个应用程序在运行时能根据客户端请求所来的国家/地区.语言的不同显示不同的 ...

  9. UVA 11865 Stream My Contest(最小树形图)

    题意:N台机器,M条有向边,总资金C,现要到搭建一个以0号机(服务器)为跟的网路,已知每条网线可以把数据从u传递到v,其带宽为d,花费为c,且d越大,传输速度越快,问能够搭建的传输速度最快的网络d值是 ...

  10. BUFFER CACHE之调整buffer cache的大小

    Buffer Cache存放真正数据的缓冲区,shared Pool里面存放的是sql指令(LC中一次编译,多次运行,加快处理性能,cache hit ratio要高),而buffer cache里面 ...