一.AFNetworking简介
AFNetworking是一个轻量级的网络请求客户端(Objective-C)是对系统网络通信模块的抽象,主要用于http/https的请求,方便一些网络请求的开发工作,如使用POST/GET以及对XML/JSON数据的解析工作。
AFNetworking分别由NSURLSession,Security,Reachability,Serialization,UIKit五部分组成。
- NSURLSession:网络通信模块(核心模块)对应 AFNetworking中的 AFURLSessionManager和对HTTP协议进行特化处理的AFHTTPSessionManager,AFHTTPSessionManager是继承于AFURLSessionmanager。
- Security:网络通讯安全策略模块对应AFSecurityPolicy。
- Reachability:网络状态监听模块对应AFNetworkReachabilityManager。
- Seriaalization:网络通信信息序列化、反序列化模块 对应 AFURLResponseSerialization。
- UIKit:对于IOSUIKit的扩展库。
GitHub:https://github.com/AFNetworking/AFNetworking
二.AFNetworking中的部分实现细节
在支持NSURLConnection的版本(3.x之前)中它实现两部分工作:NSURLConnection网络请求封装和缓存管理封装。
NSURLConnection网络请求封装
AFURLConnectionOperation.m:
+ (void)networkRequestThreadEntryPoint:(id)__unused object {
@autoreleasepool {
[[NSThread currentThread] setName:@"AFNetworking"];
NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
[runLoop addPort:[NSMachPort port] forMode:NSDefaultRunLoopMode];
[runLoop run];
}
}
+ (NSThread *)networkRequestThread {
static NSThread *_networkRequestThread = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_networkRequestThread = [[NSThread alloc] initWithTarget:self selector:@selector(networkRequestThreadEntryPoint:) object:nil];
[_networkRequestThread start];
});
return _networkRequestThread;
}
这里它通过建立一条单例线程来实现NSURLConnection的网络请求管理,并在这条线程中开启Runloop同时监听一个NSMachPort实例对象作为事件输入源,但由于这个实例对象是一个局部对象意味着AFN是不会给这个port发送消息,巧妙的开启了Runloop并维持住这个线程使其不会主动关闭。这个单例线程就是AFNetworking的守护线程。
在用网络请求的时候使用守护线程中的RunLoop:
- (void)start {
[self.lock lock];
if ([self isCancelled]) {
[self performSelector:@selector(cancelConnection) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
} else if ([self isReady]) {
self.state = AFOperationExecutingState;
[self performSelector:@selector(operationDidStart) onThread:[[self class] networkRequestThread] withObject:nil waitUntilDone:NO modes:[self.runLoopModes allObjects]];
}
[self.lock unlock];
}
- (void)operationDidStart {
[self.lock lock];
if (![self isCancelled]) {
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.outputStream open];
[self.connection start];
}
[self.lock unlock];
dispatch_async(dispatch_get_main_queue(), ^{
[[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingOperationDidStartNotification object:self];
});
}
AFNetworking的缓存机制
在AFN中它实现的缓存管理是基于系统的NSCache的接口封装:
- AFImagecache : 继承于NSCache,AFNetworking的图片内存缓存的类。
- NSURLCache : NSURLConnection的默认缓存机制,用于存储NSURLResponse对象(一个默认缓存在内存,并且可以通过一些配置操作可以持久缓存到磁盘的类)。
UIImageView+AFNetworking:
@interface AFImageCache : NSCache // singleton instantiation :
+ (id )sharedImageCache {
static AFImageCache *_af_defaultImageCache = nil;
static dispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_af_defaultImageCache = [[AFImageCache alloc] init];
// clears out cache on memory warning :
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidReceiveMemoryWarningNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification * __unused notification) {
[_af_defaultImageCache removeAllObjects];
}];
});
// key from [[NSURLRequest URL] absoluteString] :
static inline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) {
return [[request URL] absoluteString];
}
@implementation AFImageCache
// write to cache if proper policy on NSURLRequest :
- (UIImage *)cachedImageForRequest:(NSURLRequest *)request {
switch ([request cachePolicy]) {
case NSURLRequestReloadIgnoringCacheData:
case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
return nil;
default:
break;
}
return [self objectForKey:AFImageCacheKeyFromURLRequest(request)];
}
// read from cache :
- (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)request {
if (image && request) {
[self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)];
}
}
NSURLCache配置:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:2 * 1024 * 1024
diskCapacity:100 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];