介紹
AFNetworking作為iOS的網(wǎng)絡(luò)請求框架,其內(nèi)部是對iOS提供的NSURLSession
進行的封裝,從使用成面來說是非常方便的,它提供了一套非常簡單的易用的接口.AFHTTPSessionManager
這個類是對外所有接口進行的封裝,從類名來看,顧名思義,是基于HTTP協(xié)議進行的網(wǎng)絡(luò)通信.下面來介紹AFHTTPSessionManager
內(nèi)部的組成.
AFHTTPSessionManager
- HTTP協(xié)議是用于客戶端和服務(wù)端通信,HTTP通信過程包括從客戶端向服務(wù)器發(fā)出的請求,以及服務(wù)器返回客戶端的響應(yīng).
- 用于HTTP協(xié)議交互的信息稱為HTTP報文,請求端的HTTP報文叫做請求報文,響應(yīng)端的叫做響應(yīng)報文.
- 請求報文
- 請求行:說明請求類型,要訪問的資源,以及使用的HTTP版本
- 請求頭:說明服務(wù)器要使用的附加信息(鍵值對組成).
- 空行: 空行是必須要存在的,因為他是請求報文的一部分
- 請求數(shù)據(jù): 通常也叫請求報文的主體,可以添加任意的數(shù)據(jù).
- 響應(yīng)報文
- 狀態(tài)行:包括HTTP協(xié)議版本號,狀態(tài)碼,狀態(tài)信息.
- 消息報文:說明客戶端要使用的一些附加信息
- 空行:空行是必須要存在的,因為他是響應(yīng)報文的一部分.
- 響應(yīng)正文: 服務(wù)器返回給客戶端的文本信息.
在請求報文中,請求類型主要指的是HTTP支持的幾種不同的請求命令,這些命令也叫做請求方法.
下面列舉一些常見的請求方法.
http方法 | 描述 |
---|---|
GET | 從服務(wù)器向客戶端發(fā)送命名資源 |
POST | 將客戶端數(shù)據(jù)發(fā)送到一個服務(wù)器網(wǎng)關(guān)應(yīng)用程序 |
PUT | 將來自客戶端的數(shù)據(jù)存儲到一個命名服務(wù)器資源中去 |
DELETE | 從服務(wù)器中刪除命名資源 |
HEAD | 僅發(fā)送命名資源響應(yīng)中的HTTP首部 |
關(guān)于對HTTP協(xié)議這里只是粗略的介紹,關(guān)鍵是介紹HTTP的請求方法有哪些,如果詳細了解HTTP協(xié)議,請查看相應(yīng)的資料
針對上述的介紹我們知道了HTTP協(xié)議的請求方法有哪些,在AF中對這些方法做了相應(yīng)的接口封裝.
我們看到上圖AFHTTPSessionManager
繼承AFURLSessionManager
在AFHTTPSessionManager
中提供了一些常用的請求方法
- (nullable NSURLSessionDataTask *)GET:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
progress:(nullable void (^)(NSProgress *downloadProgress))downloadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
- (nullable NSURLSessionDataTask *)HEAD:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void (^)(NSURLSessionDataTask *task))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
- (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;
// 上傳文件請求
- (nullable NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
constructingBodyWithBlock:(nullable void (^)(id <AFMultipartFormData> formData))block
progress:(nullable void (^)(NSProgress *uploadProgress))uploadProgress
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
- (nullable NSURLSessionDataTask *)PUT:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
- (nullable NSURLSessionDataTask *)PATCH:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
- (nullable NSURLSessionDataTask *)DELETE:(NSString *)URLString
parameters:(nullable id)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void (^)(NSURLSessionDataTask *task, id _Nullable responseObject))success
failure:(nullable void (^)(NSURLSessionDataTask * _Nullable task, NSError *error))failure;
關(guān)于上述的請求這里就不過多的介紹了,因為在AFHTTPSessionManager
中核心方法是
// 所有的請求方法都會進入這個方法 --- 返回一個請求任務(wù)
- (NSURLSessionDataTask *)dataTaskWithHTTPMethod:(NSString *)method
URLString:(NSString *)URLString
parameters:(id)parameters
headers:(NSDictionary <NSString *, NSString *> *)headers
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;
// 對請求報文首部進行參數(shù)拼接完成之后的一個請求
NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
// 如果參數(shù) headers 有值 那么就在對請求頭進行設(shè)置
for (NSString *headerField in headers.keyEnumerator) {
[request addValue:headers[headerField] forHTTPHeaderField:headerField];
}
// 如果發(fā)生錯誤,異步返回錯誤, self.completionQueue 默認(rèn)隊列是NULL,會使用主隊列,這個參數(shù)的意義是提供給外界自行定義,在什么隊列中返回錯誤信息.
if (serializationError) {
if (failure) {
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
// 根據(jù)請求返回一個任務(wù)
__block NSURLSessionDataTask *dataTask = nil;
// 基類調(diào)用父類封裝的方法,獲取一個請求任務(wù).
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;
}
上述的請求接口除了文件上傳接口,都是對dataTaskWithHTTPMethod
進行的封裝.
也就是說該方法調(diào)用父類AFURLSessionManager
的dataTaskWithRequest:
是解讀的關(guān)鍵.關(guān)于對AFURLSessionManager
的解讀,下一篇文章有詳細的介紹.這里先介紹AF提供對外的接口類AFHTTPSessionManager
簡單使用,在該類中還有文件上傳的方法.
- (NSURLSessionDataTask *)POST:(NSString *)URLString
parameters:(id)parameters
headers:(NSDictionary<NSString *,NSString *> *)headers
constructingBodyWithBlock:(void (^)(id<AFMultipartFormData> _Nonnull))block
progress:(void (^)(NSProgress * _Nonnull))uploadProgress
success:(void (^)(NSURLSessionDataTask * _Nonnull, id _Nullable))success failure:(void (^)(NSURLSessionDataTask * _Nullable, NSError * _Nonnull))failure
{
NSError *serializationError = nil;
// 獲取一個拼接好的請求(文件上傳請求)
NSMutableURLRequest *request = [self.requestSerializer multipartFormRequestWithMethod:@"POST" URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters constructingBodyWithBlock:block error:&serializationError];
// 拼接請求頭
for (NSString *headerField in headers.keyEnumerator) {
[request addValue:headers[headerField] forHTTPHeaderField:headerField];
}
//序列化異常,默認(rèn)異步主隊列返回
if (serializationError) {
if (failure) {
dispatch_async(self.completionQueue ?: dispatch_get_main_queue(), ^{
failure(nil, serializationError);
});
}
return nil;
}
// 調(diào)用父類的方法,返回一個上傳任務(wù)
__block NSURLSessionDataTask *task = [self uploadTaskWithStreamedRequest:request progress:uploadProgress completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) {
if (error) {
if (failure) {
failure(task, error);
}
} else {
if (success) {
success(task, responseObject);
}
}
}];
// 開啟上傳任務(wù)
[task resume];
return task;
}
總結(jié)
不管是參數(shù)請求還是文件上傳,常規(guī)的套路就是:創(chuàng)建請求,獲取任務(wù),開始任務(wù).這三部分,其實這和系統(tǒng)調(diào)用的接口順序是差不多的,需要值得注意的是,參數(shù)請求和文件上傳時不一樣的,在使用層面上來說,使用起來很簡單,接口調(diào)用也不是很復(fù)雜,AF框架中針對提供的結(jié)構(gòu)也提供了相應(yīng)的測試案例,這個框架對于學(xué)習(xí)來說是非常不錯的.