一.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];

results matching ""

    No results matching ""