AFNetworking POST操作

作者: 星辰_入海 | 来源:发表于2021-09-17 14:52 被阅读0次

    AFNetworking POST操作

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

    POST操作

    - (nullable NSURLSessionDataTask *)POST:(NSString *)URLString parameters:(nullable id)parameters headers:(nullable NSDictionary <NSString *, NSString *> *)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 <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>

    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操作

        本文链接:https://www.haomeiwen.com/subject/bvajgltx.html