AFNetworking 介绍和简单实用

AFNetworking github

AFNetworking

AFNetworking 是一个网络请求封装框架,使用简单,功能强大;

在AFNetworking 3.x版本 通过封装NSURLSession,通过简单的API是我们可以简单快捷实用。

AFNetworking模块

  • NSURLSession  封装NSURLSession的模块
  • Reachability 网络状态
  • Security 网络安全配置HTTPS
  • Serialization 序列化 包括 json
  • UIKit  一些关于UIKit的Category,在UIKit中快速的使用NSURLSession模块

NSURLSession 系统请求

NSURL *requestURL = [NSURL URLWithString:[NSString stringWithFormat:@"urlStr"]];
NSURLRequest *request = [NSURLRequest requestWithURL:requestURL];
NSURLSession *session = [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
       
    }];
[dataTask resume];

这只是基本的请求,没有进行其他配置。

系统源生的请求方式,相比APNetworking使用繁琐,需要自己进行序列化和返回状态判断等。

AFNetworking 基本使用

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:@"urlStr" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
}];

使用就是这么简单那么,AFNetworking中间做了什么操作呢?

任务的创建

 [AFHTTPSessionManager manager]

+ (instancetype)manager {
    return [[[self class] alloc] initWithBaseURL:nil];
}

- (instancetype)initWithBaseURL:(NSURL *)url {
    return [self initWithBaseURL:url sessionConfiguration:nil];
}

- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    return [self initWithBaseURL:nil sessionConfiguration:configuration];
}

- (instancetype)initWithBaseURL:(NSURL *)url
           sessionConfiguration:(NSURLSessionConfiguration *)configuration
{
    //[super initWithSessionConfiguration:configuration]; 对应下面的方法
    self = [super initWithSessionConfiguration:configuration];
    if (!self) {
        return nil;
    }

    // Ensure terminal slash for baseURL path, so that NSURL +URLWithString:relativeToURL: works as expected
    if ([[url path] length] > 0 && ![[url absoluteString] hasSuffix:@"/"]) {
        url = [url URLByAppendingPathComponent:@""];
    }

    self.baseURL = url;

    self.requestSerializer = [AFHTTPRequestSerializer serializer];
    self.responseSerializer = [AFJSONResponseSerializer serializer];

    return self;
}

//AFUrlSessionManager 中的操作
- (instancetype)initWithSessionConfiguration:(NSURLSessionConfiguration *)configuration {
    self = [super init];
    if (!self) {
        return nil;
    }

    if (!configuration) {
        configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
    }

    self.sessionConfiguration = configuration;
    
    //操作队列
    self.operationQueue = [[NSOperationQueue alloc] init];
    //串行操作队列
    self.operationQueue.maxConcurrentOperationCount = 1;
    //设置session的delegate
    self.session = [NSURLSession sessionWithConfiguration:self.sessionConfiguration delegate:self delegateQueue:self.operationQueue];
    //响应数据序列化
    self.responseSerializer = [AFJSONResponseSerializer serializer];
    //身份认证
    self.securityPolicy = [AFSecurityPolicy defaultPolicy];

#if !TARGET_OS_WATCH // 非iWatch
    self.reachabilityManager = [AFNetworkReachabilityManager sharedManager];
#endif
    //根据 task.taskIdentifier 对应的 AFURLSessionManagerTaskDelegate对象的字典 
    self.mutableTaskDelegatesKeyedByTaskIdentifier = [[NSMutableDictionary alloc] init];

    self.lock = [[NSLock alloc] init];
    self.lock.name = AFURLSessionManagerLockName;
    
    //处理未完成的task
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        for (NSURLSessionDataTask *task in dataTasks) {
            [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
        }

        for (NSURLSessionUploadTask *uploadTask in uploadTasks) {
            [self addDelegateForUploadTask:uploadTask progress:nil completionHandler:nil];
        }

        for (NSURLSessionDownloadTask *downloadTask in downloadTasks) {
            [self addDelegateForDownloadTask:downloadTask progress:nil destination:nil completionHandler:nil];
        }
    }];

    return self;
}

 简化

[AFHTTPSessionManager manager]
    [AFHTTPSessionManager initWithBaseURL:] 
        [AFHTTPSessionManager initWithBaseURL: sessionConfiguration:]  
            [AFUrlSessionManager initWithSessionConfiguration:]
                [NSOperationQueue alloc] init] //请求操作队列
                [NSURLSession sessionWithConfiguration: delegate: delegateQueue:]
                [AFJSONResponseSerializer serializer] //响应序列化
                [AFSecurityPolicy defaultPolicy] //安全机制 
                [AFNetworkReachabilityManager sharedManager] //网络状态 TARGET_OS_WATCH 没有此操作
            [AFHTTPRequestSerializer serializer] //请求序列化
            [AFJSONResponseSerializer serializer] //响应序列化

 [AFHTTPSessionManager POST:  parameters:  progress: success: failure:]

请求调用简化:

[AFHTTPSessionManager POST: parameters: progress: success: failure:]
    [AFHTTPSessionManager dataTaskWithHTTPMethod: URLString:URLString parameters: uploadProgress: downloadProgress: success: failure:]
        [NSURL URLWithString:]
        [[NSMutableURLRequest alloc] initWithURL:]
        [[AFUrlRequestSerialization requestBySerializingRequest: withParameters: error:]
    
    [AFURLSessionManager dataTaskWithRequest: uploadProgress: downloadProgress: completionHandler:]
        [AFURLSessionManager addDelegateForDataTask: uploadProgress: downloadProgress: completionHandler:]

  主要是用的方法介绍:

- (NSURLSessionDataTask *)POST:(NSString *)URLString
                    parameters:(id)parameters
                      progress:(void (^)(NSProgress * _Nonnull))uploadProgress
                       success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success
                       failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
    //创建task
    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
    //启动task
    [dataTask resume];

    return dataTask;
}

创建一个NSURLSessionDataTask 并且开启请求任务。

- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
                                       URLString:(NSString *)URLString
                                      parameters:(id)parameters
                                  uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgress
                                downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgress
                                         success:(void (^)(NSURLSessionDataTask *, id))success
                                         failure:(void (^)(NSURLSessionDataTask *, NSError *))failure
{
    NSError *serializationError = nil;
    //对 request 和 parameters 进行序列化
    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method 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;
    }
    
    //创建task
    __block NSURLSessionDataTask *dataTask = nil;
    dataTask = [self dataTaskWithRequest:request
                          uploadProgress:uploadProgress
                        downloadProgress:downloadProgress
                       completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
        if (error) {
            if (failure) {
                failure(dataTask, error);
            }
        } else {
            if (success) {
                success(dataTask, responseObject);
            }
        }
    }];

    return dataTask;
}

第一部分是构造 NSMutableURLRequest

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

    NSURL *url = [NSURL URLWithString:URLString];

    NSParameterAssert(url);

    NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] initWithURL:url];
    mutableRequest.HTTPMethod = method;

    for (NSString *keyPath in AFHTTPRequestSerializerObservedKeyPaths()) {
        if ([self.mutableObservedChangedKeyPaths containsObject:keyPath]) {
            [mutableRequest setValue:[self valueForKeyPath:keyPath] forKey:keyPath];
        }
    }

    mutableRequest = [[self requestBySerializingRequest:mutableRequest withParameters:parameters error:error] mutableCopy];

	return mutableRequest;
}

 self.mutableObservedChangedKeyPaths 中的内容是通过设置NSURLRequest以下的属性 

//网络请求是否使用蜂窝移动网络
@property BOOL allowsCellularAccess API_AVAILABLE(macos(10.8), ios(6.0), watchos(2.0), tvos(9.0));

//缓存策略
@property NSURLRequestCachePolicy cachePolicy;

//cookie cookie是否添加到NSURLRequest
@property BOOL HTTPShouldHandleCookies;

//多管道 可以理解为请求是否等到上一个请求响应 在发送下一个请求 相当于同步 yes 相当于异步。
@property BOOL HTTPShouldUsePipelining API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

//请求数据类型
@property NSURLRequestNetworkServiceType networkServiceType API_AVAILABLE(macos(10.7), ios(4.0), watchos(2.0), tvos(9.0));

//请求超时时间
@property NSTimeInterval timeoutInterval;

只有设置了以上属性才会把属性添加到self.mutableObservedChangedKeyPaths中 通过观察者实现的

- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
                               withParameters:(id)parameters
                                        error:(NSError *__autoreleasing *)error
{
    NSParameterAssert(request);

    NSMutableURLRequest *mutableRequest = [request mutableCopy];

    [self.HTTPRequestHeaders enumerateKeysAndObjectsUsingBlock:^(id field, id value, BOOL * __unused stop) {
        if (![request valueForHTTPHeaderField:field]) {
            [mutableRequest setValue:value forHTTPHeaderField:field];
        }
    }];

    NSString *query = nil;
    if (parameters) {
        if (self.queryStringSerialization) {
            NSError *serializationError;
            query = self.queryStringSerialization(request, parameters, &serializationError);

            if (serializationError) {
                if (error) {
                    *error = serializationError;
                }

                return nil;
            }
        } else {
            switch (self.queryStringSerializationStyle) {
                case AFHTTPRequestQueryStringDefaultStyle:
                    query = AFQueryStringFromParameters(parameters);
                    break;
            }
        }
    }

    if ([self.HTTPMethodsEncodingParametersInURI containsObject:[[request HTTPMethod] uppercaseString]]) {
        if (query && query.length > 0) {
            mutableRequest.URL = [NSURL URLWithString:[[mutableRequest.URL absoluteString] stringByAppendingFormat:mutableRequest.URL.query ? @"&%@" : @"?%@", query]];
        }
    } else {
        // #2864: an empty string is a valid x-www-form-urlencoded payload
        if (!query) {
            query = @"";
        }
        if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
            //表单上传
            [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        }
        [mutableRequest setHTTPBody:[query dataUsingEncoding:self.stringEncoding]];
    }

    return mutableRequest;
}
  • 以设置 HTTPHeader
  • 将parameters 转换成 String 例如 @{@"name":@"123", @"phone":@"456"} => name=123&phone=456 
  • 处理参数 如果GET/HEAD/DELETE 参数拼接到urlStr后面 GET放到HTTPBODY中

第二部分是构造 NSURLSessionDataTask

- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request
                               uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
                             downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
                            completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject,  NSError * _Nullable error))completionHandler {

    __block NSURLSessionDataTask *dataTask = nil;
    url_session_manager_create_task_safely(^{
        dataTask = [self.session dataTaskWithRequest:request];
    });

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

    return dataTask;
}


- (void)addDelegateForDataTask:(NSURLSessionDataTask *)dataTask
                uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock
              downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock
             completionHandler:(void (^)(NSURLResponse *response, id responseObject, NSError *error))completionHandler
{
    //创建 AFURLSessionManagerTaskDelegate对象
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
    delegate.manager = self;
    //delegate 中保存 completionHandler 完成block
    delegate.completionHandler = completionHandler;

    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    
    [self setDelegate:delegate forTask:dataTask];

    //delegate 中保存 uploadProgressBlock 上传进度block
    delegate.uploadProgressBlock = uploadProgressBlock;
    //delegate 中保存 uploadProgressBlock 下载进度block
    delegate.downloadProgressBlock = downloadProgressBlock;
}

- (void)setDelegate:(AFURLSessionManagerTaskDelegate *)delegate
            forTask:(NSURLSessionTask *)task
{
    NSParameterAssert(task);
    NSParameterAssert(delegate);

    [self.lock lock];
    //task.taskIdentifier 唯一标识
    //把 delegate 保存到 self.mutableTaskDelegatesKeyedByTaskIdentifier字典中
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    //添加任务开始和被挂起的通知
    [self addNotificationObserverForTask:task];
    [self.lock unlock];
}

以上是创建任务的过程

 任务的调用过程

在 AFHTTPSessionManager *manager =[AFHTTPSessionManager manager]构造 中我们设置session的delegate为manager。

AFHTTPSessionManager继承AFURLSessionManager, 中实现的NSURLSession的相关代理,如下

@interface AFURLSessionManager : NSObject <NSURLSessionDelegate, NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate, NSSecureCoding, NSCopying>

这里面重点介绍

NSURLSessionTaskDelegate

//请求重定向功能 通过处理completionHandler来确定是否阻止重定向如果 completionHandler(request) 不阻止 completionHandler(nil)阻止改重定向
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                     willPerformHTTPRedirection:(NSHTTPURLResponse *)response
                                     newRequest:(NSURLRequest *)request
                              completionHandler:(void (^)(NSURLRequest * _Nullable))completionHandler;

//身份验证处理
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                            didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge 
                              completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler;

//可以重新发送新的 bodyStream 一般身份验证失败使用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                              needNewBodyStream:(void (^)(NSInputStream * _Nullable bodyStream))completionHandler;

//上传进度
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                                didSendBodyData:(int64_t)bytesSent
                                 totalBytesSent:(int64_t)totalBytesSent
                       totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;

//任务收集完完整的统计信息后发送
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didFinishCollectingMetrics:(NSURLSessionTaskMetrics *)metrics API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

//request结束(包括请求完成和任务失败)  error为nil 表示任务完成 
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
                           didCompleteWithError:(nullable NSError *)error;

 在创建NSURLSessionDataTask会保存 [AFURLSessionManager dataTaskWithRequest: uploadProgress: downloadProgress: completionHandler:]中的 uploadProgress,downloadProgress,completionHandler,当[task reusem]是 session的delegate就会调用 session的相关代理 然后通过 self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] 当session 的相关delegate方法调用时,会调用AFURLSessionManagerTaskDelegate对象中的对应方法, 然后在回调响应的block。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值