這個常用的網絡請求方法優勢有:
1.get和post都可調用此方法
2.在UIViewController類裡直接用self指針即可調用(因為這個方法是寫在UIViewController分類裡的),在其他類只需用[UIViewController new]生成個指針即可進行網絡請求
3.只需要傳入三個參數
4.代碼邏輯簡單易於理解
5.基於AFNetworking3.1.0
相關代碼:
創建一個繼承於AFHTTPSessionManager,名為AFAppDotNetAPIClient的類
代碼如下 復制代碼//AFAppDotNetAPIClient.h
#import <Foundation/Foundation.h>
#import <AFNetworking/AFNetworking.h>
@interface AFAppDotNetAPIClient : AFHTTPSessionManager
//創建單例類的方法聲明
+ (instancetype)sharedClient;
@end
//AFAppDotNetAPIClient.m
#import "AFAppDotNetAPIClient.h"
@implementation AFAppDotNetAPIClient
//創建單例類的方法實現
+ (instancetype)sharedClient{
//初始化一個靜態的類指針
static AFAppDotNetAPIClient *sharedClient;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedClient = [AFAppDotNetAPIClient new];
//AFNetworking請求頭信息相關設置
sharedClient.requestSerializer = [AFJSONRequestSerializer serializer];
[sharedClient.requestSerializer setValue:@"application/json;charset=utf-8" forHTTPHeaderField:@"Content-Type"];
//AFNetworking獲取到的參數相關設置
sharedClient.responseSerializer = [AFJSONResponseSerializer serializer];
sharedClient.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/html", @"text/javascript", nil];
//SSL相關設置
sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
});
return sharedClient;
}
@end
寫在UIViewController分類裡的網絡請求方法:
代碼如下 復制代碼- (NSURLSessionDataTask *)defaultRequestwithURL: (NSString *)URL withParameters: (NSDictionary *)parameters withMethod: (NSString *)method withBlock:(void (^)(NSDictionary *dict, NSError *error))block
{
//默認打印傳入的實參
#ifdef DEBUG
NSLog(@"common method = %@", method);//get 或 post
NSLog(@"common URL = %@", URL);//所請求的網址
NSLog(@"common parameters = %@", parameters);//傳入的參數
#endif
//根據method字符串判斷調用AFNetworking裡的get方法還是post方法
if ( [method isEqualToString:@"GET"] ) {//所用到的是AFNetworking3.1.0裡的方法,其新加了progress進度block
return [[AFAppDotNetAPIClient sharedClient] GET:URL parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable JSON) {
#ifdef DEBUG
NSLog(@"common get json = %@", JSON);//打印獲取到的json
#endif
NSDictionary *dict = JSON;//直接返回字典,方便使用
if (block) {
block(dict, nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//如果請求出錯返回空字典和NSError指針
if (block) {
block([NSDictionary dictionary], error);//這一點算是比較坑的地方了,因為比如我要根據一個字段來判斷是否請求成功,我對一個空字典@{},
//根據一個key取value:[@{} objectForKey:@"errorCode"],
//然後判斷字符串的intValue是否等於0:[[@{} objectForKey:@"errorCode"] intValue] == 0是返回1的。
//我想的解決辦法就是從服務器端來改,返回的字段key用isSuccess,value是字符串True或False即可解決,
//但是這樣又只能知道成功或失敗並不能根據errorCode碼進行其他操作,因為errorCode可以為0、1、2、3等等。
}
//從指針級判斷error是否為空,如果不為空就打印error
if (error) {
NSLog(@"%@",error);
}
}];
}
//post相關代碼
return [[AFAppDotNetAPIClient sharedClient]POST:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable JSON) {
#ifdef DEBUG
NSLog(@"common post json = %@", JSON);//打印獲取到的json
#endif
NSDictionary *dict = JSON;//直接返回字典,方便使用
if (block) {
block(dict, nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//如果請求出錯返回空字典和NSError指針
if (block) {
block([NSDictionary dictionary], error);
}
//從指針級判斷error是否為空,如果不為空就打印error
if (error) {
NSLog(@"%@",error);
}
}];
//返回值暫時用不到,不需要創建變量接收;傳進的self指針也沒有用到所以這個方法可移植性很強
}
-(void)request
{
//測試網絡請求方法
//1.所用到的網址是本人以前抓到的,API是用php寫的,服務器很穩定,我常用來測試,也僅供測試
//2.get參數 start和end傳無符號整數
NSDictionary *parameters = @{
@"type":@"list",
@"city":@"2",
@"lid":@"31",
@"sortby":@"1",
@"start":@"0",
@"end":@"3"
};
[self defaultRequestwithURL:@"/api.php" withParameters:parameters withMethod:@"GET" withBlock:^(NSDictionary *dict, NSError *error) {
}];
}
額外附送多圖上傳方法,同樣基於AFNetworking3.1.0,和以上方法類似所以不加詳解注釋了:
代碼如下 復制代碼-(void)startMultiPartUploadTaskWithURL:(NSString *)url
imagesArray:(NSArray *)images
parameterOfimages:(NSString *)parameter
parametersDict:(NSDictionary *)parameters
compressionRatio:(float)ratio
succeedBlock:(void (^)(NSDictionary *dict))succeedBlock
failedBlock:(void (^)(NSError *error))failedBlock{
if (images.count == 0) {
NSLog(@"圖片數組計數為零");
return;
}
for (int i = 0; i < images.count; i++) {
if (![images[i] isKindOfClass:[UIImage class]]) {
NSLog(@"images中第%d個元素不是UIImage對象",i+1);
}
}
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
int i = 0;
//根據當前系統時間生成圖片名稱
NSDate *date = [NSDate date];
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateFormat:@"yyyy年MM月dd日"];
NSString *dateString = [formatter stringFromDate:date];
for (UIImage *image in images) {
NSString *fileName = [NSString stringWithFormat:@"%@%d.png",dateString,i];
NSData *imageData;
if (ratio > 0.0f && ratio < 1.0f) {
imageData = UIImageJPEGRepresentation(image, ratio);
}else{
imageData = UIImageJPEGRepresentation(image, 1.0f);
}
[formData appendPartWithFileData:imageData name:parameter fileName:fileName mimeType:@"image/jpg/png/jpeg"];
}
} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableContainers error:nil];
NSLog(@"common post json = %@", dict);
succeedBlock(dict);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (error) {
failedBlock(error);
NSLog(@"%@",error);
}
}];
}