iOS WebServiceFramework网络服务框架浅解
网络服务几乎是每一款成功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网络服务框架浅解的更多相关文章
- iOS 开发之照片框架详解(2)
一. 概况 本文接着 iOS 开发之照片框架详解,侧重介绍在前文中简单介绍过的 PhotoKit 及其与 ALAssetLibrary 的差异,以及如何基于 PhotoKit 与 AlAssetLib ...
- iOS 开发之照片框架详解之二 —— PhotoKit 详解(下)
本文链接:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 这里接着前文<iOS ...
- iOS 开发之照片框架详解之二 —— PhotoKit 详解(上)
转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework-part-two.html 一. 概况 本文接着 iOS 开 ...
- iOS 开发之照片框架详解
转载自:http://kayosite.com/ios-development-and-detail-of-photo-framework.html 一. 概要 在 iOS 设备中,照片和视频是相当重 ...
- greenev —— Python 异步网络服务框架
greenev是一个基于greenlet协程,事件驱动,非阻塞socket模型的Python网络服务框架,它使得可以编写同步的代码,却得到异步执行的优点. 本项目受到gevent, openresty ...
- [apue] 一个工业级、跨平台的 tcp 网络服务框架:gevent
作为公司的公共产品,经常有这样的需求:就是新建一个本地服务,产品线作为客户端通过 tcp 接入本地服务,来获取想要的业务能力. 与印象中动辄处理成千上万连接的 tcp 网络服务不同,这个本地服务是跑在 ...
- 一个工业级、跨平台、轻量级的 tcp 网络服务框架:gevent
前言 作为公司的公共产品,经常有这样的需求:就是新建一个本地服务,产品线作为客户端通过 tcp 接入本地服务,来获取想要的业务能力.与印象中动辄处理成千上万连接的 tcp 网络服务不同,这个本地服务是 ...
- iOS 开发之照片框架详解(1)
http://kayosite.com/ios-development-and-detail-of-photo-framework.html/comment-page-1 一. 概要 在 iOS 设备 ...
- iOS 开发之照片框架详解(3)
http://kayosite.com/ios-development-and-detail-of-photo-framework-part-three.html 三. 常用方法的封装 虽然 Phot ...
随机推荐
- 【HDOJ】4080 Stammering Aliens
1. 题目描述给定一个长为$n \in [1, 4000]$的字符串,求其中长度最长的子串,并且该子串在原串中出现至少$m$次,并求最右起始位置. 2. 基本思路两种方法:二分+后缀数组,或者二分+哈 ...
- CY7C68013A的一点总结
一. 值得参考的资料:FX2 TechRefManual.USB应用开发宝典. LabVIEW-USB通信简单教程(用于参考生成labview驱动程序).USB设备请求和描述符整理(仅用于理解描述符的 ...
- Effective C++学习笔记 条款06:如不想使用编译器自动生成的函数,就该明确拒绝
一.为驳回编译器自动提供的机能,可将相应成员函数声明为private并且不予实现.(如果你仅仅是自己不实现的话,编译器会帮你实现) 如: class A { public: A(const strin ...
- UVa 1640 (计数) The Counting Problem
题意: 统计[a, b]或[b, a]中0~9这些数字各出现多少次. 分析: 这道题可以和UVa 11361比较来看. 同样是利用这样一个“模板”,进行区间的分块,加速运算. 因为这里没有前导0,所以 ...
- Share SDK 第三方登录
import java.util.HashMap; import org.apache.http.Header; import android.app.Activity; import android ...
- 【C#学习笔记】播放wma/mp3文件
using System; using System.Runtime.InteropServices; namespace ConsoleApplication { class Program { [ ...
- java 错误:找不到或无法加载主类的解决办法
此类错误的常见解决办法: 1.是因为.java文件不在项目的src路径内,也就是说源代码未被eclipse编译,字节码不存在无法运行了在项目名上右键 -> Builder Path -> ...
- Dataguard三种保护模式
Oracle Data Guard 提供三种高水平的数据保护模式来平衡成本.可用性.性能和事务保护.可以使用任意可用管理界面来轻松地设置这些模式.要确定适当的数据保护模式,企业需要根据用户对系统响应时 ...
- Android自定义的webView——可实现的网页文本的复制
package com.example.customlinearlayout.view; import android.app.ProgressDialog; import android.conte ...
- .NET之美——C#中的委托和事件(续)
C#中的委托和事件(续) 引言 如果你看过了 C#中的委托和事件 一文,我想你对委托和事件已经有了一个基本的认识.但那些远不是委托和事件的全部内容,还有很多的地方没有涉及.本文将讨论委托和事件一些更为 ...