AFNetworking POST操作
網(wǎng)絡(luò)請求部分,我們上一片分析了GET請求源碼部分,通過這篇我們來了解關(guān)于POST請求的源碼部分,其實POST和GET實現(xiàn)過程是一樣的就是中間處理部分會出現(xiàn)略微差異。
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;
}
傳入的參數(shù)和GET方法相同:
- 請求的URL網(wǎng)址;
- 請求頭(字典);
- 上傳進度;
- 成功回調(diào);
- 失敗回調(diào);
同樣,返回的是一個NSURLSessionDataTask對象,并且實現(xiàn)了啟動任務(wù)[dataTask resume];。
進入POST源碼我們可以看到,實際上操作是和GET方法調(diào)用了一個方法。在這里我們就能清楚的意識到,從這里開始整個流程是一樣的,不過對于POST和GET方法是通過之前對Method來區(qū)分對待的。
在GET中method傳入的是@"GET",而在POST中傳入的是@"POST"。
- GET
[self dataTaskWithHTTPMethod:@"GET" URLString:URLString parameters:parameters headers:headers uploadProgress:nil downloadProgress:downloadProgress success:success failure:failure];
- POST
[self dataTaskWithHTTPMethod:@"POST" URLString:URLString parameters:parameters headers:headers uploadProgress:uploadProgress downloadProgress:nil success:success failure:failure];
保存方法
最后到達方法內(nèi)部,進行保存了HTTP請求方式為POST,此時的method為POST。
mutableRequest.HTTPMethod = method;
AFNetworking應(yīng)該注意的好的編程方法
這樣部分摘自GET和POST共同方法中,我們知道做網(wǎng)絡(luò)編程中,會出現(xiàn)錯誤問題,AFNetworking為我們做出了很好的典范,當我們設(shè)置了NSError *error后,需要判斷如果error出現(xiàn)了錯誤的情況,如果出現(xiàn)了錯誤,我們則需要開辟一條新的線程來做錯誤處理。
if (serializationError) {
if (failure) {
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
網(wǎng)絡(luò)編程遇到線程錯誤問題是非常常見的,因此,對于錯誤處理AFNetworking做的非常完善。
反向思考
看到這里,GET和POST的處理方式,是大抵相同的。我們反著梳理一遍思路。首先,要做GET和POST請求,我們需要知道請求網(wǎng)址,因為POST需要的內(nèi)容比GET多請求頭,因此,設(shè)計方法時候,將方法安裝POST方法設(shè)計,當GET調(diào)用時候,不需要的地方傳入nil即可,此時要能請求POST和GET方法,還需要生成NSURLSessionDataTask,要DataTask就需要NSURLRequest。所以,我們就專門對Request進行一次封裝,從用戶傳入的請求頭和請求方法獲得信息給Request。這樣,Request是帶著信息傳給NSURLSessionDataTask,這樣,就可以生成一個具有這些信息的DataTask。然后,啟動任務(wù)即可。
或許,你看到這里有疑惑,那成功做的事情和失敗做的事情以及進度條是怎么做的呢,的確,設(shè)計方法時候,AFNetworking將這三個板塊設(shè)計成為Block回調(diào),這樣就可以等請求完成后,繼續(xù)運行用戶傳入的東西。
這些回調(diào)原來系統(tǒng)需要使用協(xié)議來使用,AFNetworking自然會遵循這一個操作,因此,我們來看看AFNetworking封裝的協(xié)議。
AFNetworking封裝協(xié)議
- (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;
/* 任務(wù)描述 */
dataTask.taskDescription = self.taskDescriptionForSessionTasks;
[self setDelegate:delegate forTask:dataTask];
/* 傳入更新Block和下載Block塊 */
delegate.uploadProgressBlock = uploadProgressBlock;
delegate.downloadProgressBlock = downloadProgressBlock;
}
@interface AFURLSessionManagerTaskDelegate : NSObject <NSURLSessionTaskDelegate, NSURLSessionDataDelegate, NSURLSessionDownloadDelegate>
AFNetworking創(chuàng)建一個AFURLSessionManagerTaskDelegate來管理協(xié)議,這個協(xié)議繼承了NSURLSessionTaskDelegate,NSURLSessionDataDelegate,NSURLSessionDownloadDelegate這三個我們經(jīng)常使用的三個協(xié)議。
@property (nonatomic, weak) AFURLSessionManager *manager; //url話語管理者
@property (nonatomic, strong) NSMutableData *mutableData; //數(shù)據(jù)
@property (nonatomic, strong) NSProgress *uploadProgress; //更新進度
@property (nonatomic, strong) NSProgress *downloadProgress; //下載進度
@property (nonatomic, copy) NSURL *downloadFileURL; //下載文件的路徑
AFURLSessionManagerTaskDelegate將存儲每一個協(xié)議內(nèi)容,包括上傳進度,下載進度,下載文件路徑等。
在設(shè)置協(xié)議中,有趣的是,AFNetworking向我們展示了區(qū)別于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來鎖住線程和釋放線程操作。通過字典存儲任務(wù)標識。為每個任務(wù)添加了通知。
@property (readwrite, nonatomic, strong) NSMutableDictionary *mutableTaskDelegatesKeyedByTaskIdentifier;
在這一步里面也進行了計算進度的操作。
AFURLSessionManagerTaskDelegate *delegate = [[AFURLSessionManagerTaskDelegate alloc] initWithTask:dataTask];
至此,我們已經(jīng)分析了大部分源碼了,如果有興趣的話,可以放下在AFNetworking中有對Delete實現(xiàn)的大量封裝,這一個封裝操作,下一篇會做詳細介紹,來幫助梳理如何學(xué)習AFNetworking一樣封裝Delegate。
中文源碼下載
AFNetworking中文源碼: GitHub