AFNetworking 主要工作原理和关键部分的详细分析

696 阅读3分钟

AFNetworking 是一个强大的 iOS 和 macOS 网络库,它通过封装 NSURLSession 和其他底层网络库,提供了一个简洁且强大的 API 接口。以下是 AFNetworking 的主要工作原理和关键部分的详细分析:

核心组件

AFNetworking 主要由以下几个核心组件组成:

  • AFHTTPSessionManager: 基于 NSURLSession 的高级管理器,提供 HTTP 请求的便利方法。
  • AFURLSessionManager: 低级别的会话管理器,管理 NSURLSession 的生命周期和委托。
  • AFNetworkReachabilityManager: 网络可达性检查工具,监测网络状态的变化。
  • AFSecurityPolicy: 安全策略对象,处理 SSL 证书验证。

AFHTTPSessionManager 实现

AFHTTPSessionManagerAFNetworking 中最常用的类,继承自 AFURLSessionManager,并扩展了许多具体用于处理 HTTP 请求的便利方法。

@implementation AFHTTPSessionManager

- (instancetype)initWithBaseURL:(NSURL *)url sessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }
    
    self.baseURL = url;
    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}

- (NSURLSessionDataTask *)GET:(NSString *)URLString
                   parameters:(id)parameters
                      headers:(NSDictionary <NSString *, NSString *> *)headers
                     progress:(void (^)(NSProgress *downloadProgress))downloadProgress
                      success:(void (^)(NSURLSessionDataTask *task, id responseObject))success
                      failure:(void (^)(NSURLSessionDataTask *task, NSError *error))failure
{
    NSError *serializationError = nil;
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:@"GET" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
    
    if (serializationError) {
        if (failure) {
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
        }
        return nil;
    }

    for (NSString *field in headers) {
        [request setValue:headers[field] forHTTPHeaderField:field];
    }

    NSURLSessionDataTask *dataTask = [self dataTaskWithRequest:request uploadProgress:nil downloadProgress:downloadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
        if (error) {
            if (failure) {
                failure(dataTask, error);
            }
        } else {
            if (success) {
                success(dataTask, responseObject);
            }
        }
    }];
    
    [dataTask resume];

    return dataTask;
}

@end

请求和响应序列化

AFNetworking 提供了多种序列化器来处理请求参数和响应数据:

@implementation AFHTTPRequestSerializer

- (NSMutableURLRequest *)requestWithMethod:(NSString *)method
                                 URLString:(NSString *)URLString
                                parameters:(id)parameters
                                     error:(NSError *__autoreleasing *)error
{
    NSParameterAssert(method);
    NSParameterAssert(URLString);

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:URLString]];
    request.HTTPMethod = method;

    if (parameters) {
        if ([method isEqualToString:@"GET"] || [method isEqualToString:@"HEAD"] || [method isEqualToString:@"DELETE"]) {
            NSString *query = AFQueryStringFromParameters(parameters);
            if (query && query.length > 0) {
                URLString = [URLString stringByAppendingFormat:[URLString rangeOfString:@"?"].location == NSNotFound ? @"?%@" : @"&%@", query];
                request.URL = [NSURL URLWithString:URLString];
            }
        } else {
            request.HTTPBody = [NSJSONSerialization dataWithJSONObject:parameters options:0 error:error];
        }
    }

    return request;
}

@end

会话管理

AFURLSessionManager 是对 NSURLSession 的封装,管理会话及其任务的生命周期:

@implementation AFURLSessionManager

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    self.sessionConfiguration = configuration;
    self.session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    
    self.operationQueue = [[NSOperationQueue alloc] init];
    self.operationQueue.maxConcurrentOperationCount = 1;

    return self;
}

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                                uploadProgress:(void (^)(NSProgress *uploadProgress))uploadProgressBlock
                              downloadProgress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock
                             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    NSURLSessionDataTask *dataTask = [self.session dataTaskWithRequest:request];

    [self setDelegateForTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler];

    return dataTask;
}

- (void)setDelegateForTask:(NSURLSessionTask *)task
           uploadProgress:(void (^)(NSProgress *uploadProgress))uploadProgressBlock
         downloadProgress:(void (^)(NSProgress *downloadProgress))downloadProgressBlock
        completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] init];
    delegate.manager = self;
    delegate.completionHandler = completionHandler;
    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;

    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [task addObserver:self forKeyPath:NSStringFromSelector(@selector(state)) options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:AFTaskStateChangedContext];
}

@end

网络可达性

AFNetworkReachabilityManager 利用 SCNetworkReachability 监控网络状态变化:

@implementation AFNetworkReachabilityManager

+ (instancetype)sharedManager {
    static AFNetworkReachabilityManager *_sharedManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _sharedManager = [self manager];
    });

    return _sharedManager;
}

- (void)startMonitoring {
    SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, [self.baseURL.host UTF8String]);

    self.networkReachability = reachability;

    SCNetworkReachabilityContext context = {0, (__bridge void *)(self), NULL, NULL, NULL};
    SCNetworkReachabilitySetCallback(reachability, AFNetworkReachabilityCallback, &context);
    SCNetworkReachabilityScheduleWithRunLoop(reachability, CFRunLoopGetMain(), kCFRunLoopCommonModes);

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
        SCNetworkReachabilityFlags flags;
        if (SCNetworkReachabilityGetFlags(reachability, &flags)) {
            AFPostReachabilityStatusChange(flags);
        }
    });
}

@end

static void AFNetworkReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNetworkReachabilityFlags flags, void *info) {
    AFNetworkReachabilityStatus status = AFNetworkReachabilityStatusForFlags(flags);
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:AFNetworkingReachabilityDidChangeNotification object:nil userInfo:@{ AFNetworkingReachabilityNotificationStatusItem: @(status) }];
    });
}

安全策略

AFSecurityPolicy 用于 SSL 证书验证:

@implementation AFSecurityPolicy

+ (instancetype)policyWithPinningMode:(AFSSLPinningMode)pinningMode {
    AFSecurityPolicy *securityPolicy = [[self alloc] init];
    securityPolicy.SSLPinningMode = pinningMode;

    return securityPolicy;
}

- (BOOL)evaluateServerTrust:(SecTrustRef)serverTrust forDomain:(NSString *)domain {
    switch (self.SSLPinningMode) {
        case AFSSLPinningModeNone:
            return YES;

        case AFSSLPinningModePublicKey:
        case AFSSLPinningModeCertificate:
            return [self.pinnedCertificates containsObject:(__bridge id)(serverTrust)];

        default:
            return NO;
    }
}

@end

异步处理

AFNetworking 使用 GCD 来管理并发队列:

dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
    if (success) {
        success(task, responseObject);
    }
});

总结来说,AFNetworking 通过封装 NSURLSession 提供了简洁且强大的 API 接口,结合请求序列化、响应序列化、网络可达性和 SSL 安全策略等模块化设计,使得网络请求和响应处理更加简便和灵活。