您的位置:首页 > 移动开发 > IOS开发

iOS开源项目学习—— AFNetworking

2015-09-25 18:41 417 查看
网络上已有对AFNetworking的很好的分析,如:

AFNetworking2.0源码解析<一>

AFNetworking2.0源码解析<二>

AFNetworking2.0源码解析<三>

AFNetworking2.0源码解析<四>

对于AFNetworking的详细介绍,可以参考作者Mattt Thompson的在AFNetworking 2.0的介绍。

NSURLConnection

AFURLConnectionOperation继承自NSOperation,并实现了NSURLConnection的代理方法。它是所有网络请求操作的基类。

AFHTTPRequestOperation继承自AFURLConnectionOperation,使用HTTP或者HTTPS来进行请求。它封装了acceptable status codes 和content types的类型,这是用来确定一个请求失败或成功的。

AFHTTPRequestOperationManager封装了web应用通过HTTP请求的通用模式,包括请求的创建、响应的序列化,网络状态的监控和安全,以及网络请求的管理。

AFURLConnectionOperation

NSRecursiveLock

AFURLConnectionOperation在很多地方都使用到了递归锁。例如:

//字符串编码格式
- (NSStringEncoding)responseStringEncoding {
[self.lock lock];
if (!_responseStringEncoding && self.response) {
NSStringEncoding stringEncoding = NSUTF8StringEncoding;
if (self.response.textEncodingName) {
CFStringEncoding IANAEncoding = CFStringConvertIANACharSetNameToEncoding((__bridge CFStringRef)self.response.textEncodingName);
if (IANAEncoding != kCFStringEncodingInvalidId) {
stringEncoding = CFStringConvertEncodingToNSStringEncoding(IANAEncoding);
}
}

self.responseStringEncoding = stringEncoding;
}
[self.lock unlock];

return _responseStringEncoding;
}


NSRecursiveLock这种“递归锁”,线程能够多次持有该锁,而不会出现“死锁”现象。

OC中,还有其它形式的锁,参考内容来自:

Objective-C中不同方式实现锁(一)

Objective-C中不同方式实现锁(二)

Effective Objective-C Notes:GCD 实现同步锁

iOS多线程编程指南(四)线程同步

ios笔记– 多线程应该知道的那几件事 GCD NSThread NSOperation

NSURLConnection与NSRunLoop

在- (void)operationDidStart 方法中,有如下形式的代码:

self.connection = [[NSURLConnection alloc] initWithRequest:self.request delegate:self startImmediately:NO];

NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
for (NSString *runLoopMode in self.runLoopModes) {
[self.connection scheduleInRunLoop:runLoop forMode:runLoopMode];
[self.outputStream scheduleInRunLoop:runLoop forMode:runLoopMode];
}


self.runLoopModes为:

self.runLoopModes = [NSSet setWithObject:NSRunLoopCommonModes];


至于为什么NSURLConnection要与NSRunLoop结合起来使用,请参考一个异步网络请求的坑:关于NSURLConnection和NSRunLoopCommonModes

首先,如果是直接调用NSURLConnection的initWithRequest:delegate:startImmediately:(第三个参数用YES,这个是designated

initializer)或者方法initWithRequest:delegate:时,NSURLConnection会默认运行在NSDefaultRunLoopMode模式下,即使再使用scheduleInRunLoop:forMode:设置运行模式也没有用。如果NSURLConnection运行在NSDefaultRunLoopMode下,何为Run

Loop的模式Mode,请参考这篇Blog), 这篇Blog提到NSDefaultRunLoopMode是Run

Loop默认的运行模式,用于处理除了NSConnection对象的事件。

然而如果NSURLConnection是运行在NSDefaultRunLoopMode,而当前线程是主线程,并且UI上有类似滚动这样的操作,那么主线程的Run

Loop会运行在UITrackingRunLoopMode下,就无法响应NSURLConnnection的回调。此时需要首先使用initWithRequest:delegate:startImmediately:(第三个参数为NO)生成NSURLConnection,再重新设置NSURLConnection的运行模式为NSRunLoopCommonModes,那么UI操作和回调的执行都将是非阻塞的,因为NSRunLoopCommonModes是一组run

loop mode的集合,默认情况下包含了NSDefaultRunLoopMode和UITrackingRunLoopMode。

AFHTTPRequestSerializer

AFHTTPRequestSerializer主要用来创建格式化请求参数,生成HTTP Header。

在其+ (instancetype)serializer类方法中,会设置Accept-Language、User-Agent等:

设置Accept-Language

NSMutableArray *acceptLanguagesComponents = [NSMutableArray array];
[[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
float q = 1.0f - (idx * 0.1f);
[acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]];
*stop = q <= 0.5f;
}];
[self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];


 Accept-Language: zh-cn,zh;q=0.5   

意思:浏览器支持的语言分别是中文和简体中文,优先支持简体中文。

详解:Accept-Language表示浏览器所支持的语言类型;   

zh-cn表示简体中文;zh 表示中文;

  q是权重系数,范围 0 =< q <= 1,q 值越大,请求越倾向于获得其“;”之前的类型表示的内容,若没有指定 q

值,则默认为1,若被赋值为0,则用于提醒服务器哪些是浏览器不接受的内容类型。

设置User-Agent

User-Agent是Http协议中的一部分,属于头域的组成部分,User Agent也简称UA。用较为普通的一点来说,是一种向访问网站提供你所使用的浏览器类型、操作系统及版本、CPU 类型、浏览器渲染引擎、浏览器语言、浏览器插件等信息的标识。UA字符串在每次浏览器 HTTP 请求时发送到服务器!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: