AFNetworking POST操作

AFNetworking POST操作

网络请求部分,我们上一片分析了GET请求源码部分,通过这篇我们来了解关于POST请求的源码部分,其实POST和GET实现过程是一样的就是中间处理部分会出现略微差异。

POST操作

- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters headers:(nullable NSDictionary  *)headers progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure
{
    NSURLSessionDataTask *dataTask = [self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters headers:headers uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
    
    [dataTask resume];
    
    return dataTask;
}

传入的参数和GET方法相同:

  1. 请求的URL网址;
  2. 请求头(字典);
  3. 上传进度;
  4. 成功回调;
  5. 失败回调;

同样,返回的是一个NSURLSessionDataTask对象,并且实现了启动任务[dataTask resume];。

进入POST源码我们可以看到,实际上操作是和GET方法调用了一个方法。在这里我们就能清楚的意识到,从这里开始整个流程是一样的,不过对于POST和GET方法是通过之前对Method来区分对待的。
在GET中method传入的是@"GET",而在POST中传入的是@"POST"。

  1. GET
[self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:downloadProgress success:success failure:failure];
  1. POST
[self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters headers:headers uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];

保存方法

最后到达方法内部,进行保存了HTTP请求方式为POST,此时的method为POST。

mutableRequest.HTTPMethod = method;

AFNetworking应该注意的好的编程方法

这样部分摘自GET和POST共同方法中,我们知道做网络编程中,会出现错误问题,AFNetworking为我们做出了很好的典范,当我们设置了NSError *error后,需要判断如果error出现了错误的情况,如果出现了错误,我们则需要开辟一条新的线程来做错误处理。

if (serializationError) {
        if (failure) {
            dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
                failure(nil, serializationError);
            });
        }
         
        return nil;
}

网络编程遇到线程错误问题是非常常见的,因此,对于错误处理AFNetworking做的非常完善。

反向思考

看到这里,GET和POST的处理方式,是大抵相同的。我们反着梳理一遍思路。首先,要做GET和POST请求,我们需要知道请求网址,因为POST需要的内容比GET多请求头,因此,设计方法时候,将方法安装POST方法设计,当GET调用时候,不需要的地方传入nil即可,此时要能请求POST和GET方法,还需要生成NSURLSessionDataTask,要DataTask就需要NSURLRequest。所以,我们就专门对Request进行一次封装,从用户传入的请求头和请求方法获得信息给Request。这样,Request是带着信息传给NSURLSessionDataTask,这样,就可以生成一个具有这些信息的DataTask。然后,启动任务即可。
或许,你看到这里有疑惑,那成功做的事情和失败做的事情以及进度条是怎么做的呢,的确,设计方法时候,AFNetworking将这三个板块设计成为Block回调,这样就可以等请求完成后,继续运行用户传入的东西。

这些回调原来系统需要使用协议来使用,AFNetworking自然会遵循这一个操作,因此,我们来看看AFNetworking封装的协议。

AFNetworking封装协议

- (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
{
    /* 通过dataTask实例化一个delegate对象 */
    AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
    
    /* 将自身传给delegate对象的管理者 */
    delegate.manager = self;
    
    delegate.completionHandler = completionHandler;

    /* 任务描述 */
    dataTask.taskDescription = self.taskDescriptionForSessionTasks;
    [self setDelegate:delegate forTask:dataTask];

    /* 传入更新Block和下载Block块 */
    delegate.uploadProgressBlock = uploadProgressBlock;
    delegate.downloadProgressBlock = downloadProgressBlock;
}

@interface AFURLSessionManagerTaskDelegate : NSObject

AFNetworking创建一个AFURLSessionManagerTaskDelegate来管理协议,这个协议继承了NSURLSessionTaskDelegate,NSURLSessionDataDelegate,NSURLSessionDownloadDelegate这三个我们经常使用的三个协议。

@property (nonatomic, weak) AFURLSessionManager *manager; //url话语管理者
@property (nonatomic, strong) NSMutableData *mutableData; //数据
@property (nonatomic, strong) NSProgress *uploadProgress; //更新进度
@property (nonatomic, strong) NSProgress *downloadProgress; //下载进度
@property (nonatomic, copy) NSURL *downloadFileURL; //下载文件的路径

AFURLSessionManagerTaskDelegate将存储每一个协议内容,包括上传进度,下载进度,下载文件路径等。

在设置协议中,有趣的是,AFNetworking向我们展示了区别于RAC锁住线程的方法。

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

    [self.lock lock];
    self.mutableTaskDelegatesKeyedByTaskIdentifier[@(task.taskIdentifier)] = delegate;
    [self addNotificationObserverForTask:task];
    
    [self.lock unlock];
}

利用NSLock来锁住线程和释放线程操作。通过字典存储任务标识。为每个任务添加了通知。

@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;

在这一步里面也进行了计算进度的操作。

AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];

至此,我们已经分析了大部分源码了,如果有兴趣的话,可以放下在AFNetworking中有对Delete实现的大量封装,这一个封装操作,下一篇会做详细介绍,来帮助梳理如何学习AFNetworking一样封装Delegate。

中文源码下载

AFNetworking中文源码: GitHub

你可能感兴趣的:(AFNetworking POST操作)