简介
-
目前的iOS开发,如果选择Objective-C的话,网络库基本上会选择AFNetworking
-
网络协议一般都会上HTTPS,数据类型一般都会选择JSON
-
HTTPS的Method应该是GET和POST都有。当然,统一使用POST也是可以的,也更简单。
方案一:直接使用Http接口
既然是HTTPS,而且是JSON解析,AFNetworking也提供了顶层的POST和GET接口,封装一下很方便。
/**
http method (1:POST,2:GET) ,
*/
typedef NS_ENUM(NSInteger,PDAHTTPMethod) {
PDAHTTPMethodPOST = 1,
PDAHTTPMethodGET = 2,
};
+ (void)networkWithMethod:(PDAHTTPMethod)method
url:(NSString *)urlString
parameters:(nullable NSDictionary *)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void(^)(id _Nullable response))success
failure:(nullable void(^)(NSError * _Nullable error))failure {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer = [AFJSONRequestSerializer serializerWithWritingOptions:NSJSONWritingPrettyPrinted];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingMutableContainers];
if (method == PDAHTTPMethodPOST) {
[manager POST:urlString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success != nil) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure != nil) {
failure(error);
}
}];
}
if (method == PDAHTTPMethodGET) {
[manager GET:urlString parameters:parameters headers:headers progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success != nil) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure != nil) {
failure(error);
}
}];
}
}
-
这样封装非常简介,就是把不需要的process参数给抛弃了。success和failure参数简化了。
-
大多数情况是没有问题。JSON解析的事情也不需要考虑。
-
但是有时候会报错
unacceptable content-type: text/plain
,这个是AFNetworking本身的问题,网上也有类似的文章。
iOS 数据请求 unacceptable content-type: text/plain -
按照上面文章的说法,需要修改AFNetworking源代码,这个违背了使用第三方库的基本原则。所以不是很好。考虑使用更底层的接口进行封装。
方案二:封装NSURLSessionDataTask接口
-
不管是POST还是GET,都是一种DataTask;
-
一些顶层参数,比如method,url之类的,都在request中配置;
-
有些需求,比如参数加解密,有时候也需要自定义。用太顶层的接口就不大方便。
// 包装dataTaskWithRequest
+ (void)HTTTPWithMethod:(PDAHTTPMethod)method
url:(NSString *)urlString
parameters:(nullable NSDictionary *)parameters
headers:(nullable NSDictionary <NSString *, NSString *> *)headers
success:(nullable void(^)(id _Nullable response))success
failure:(nullable void(^)(NSError * _Nullable error))failure {
// url
NSURL *url = nil;
if (method == PDAHTTPMethodPOST) {
url = [NSURL URLWithString:urlString];
}
if (method == PDAHTTPMethodGET) {
// get请求拼接参数
NSMutableString *urlWithQury = [NSMutableString stringWithString:urlString];
if ((parameters != nil) && (parameters.count > 0)) {
[urlWithQury appendString:@"?"];
NSArray *keys = parameters.allKeys;
for (NSInteger i = 0; i < keys.count; i++) {
NSString *keyAndValue = [NSString stringWithFormat:@"%@=%@", keys[i], [parameters objectForKey:keys[i]]];
[urlWithQury appendString:keyAndValue];
if (i != (parameters.count - 1)){
[urlWithQury appendString:@"&"];
}
}
}
url = [NSURL URLWithString:[urlWithQury copy]];
}
// request
NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
// method
if (method == PDAHTTPMethodPOST) {
[request setHTTPMethod:@"POST"];
}
if (method == PDAHTTPMethodGET) {
[request setHTTPMethod:@"GET"];
}
// body 只有POST才需要设置body
if ((parameters != nil) && (parameters.count > 0) && (method == PDAHTTPMethodPOST)) {
NSData *jsonData = [PDAJSON dictionaryToJsonData:parameters];
if (jsonData != nil) {
[request setHTTPBody:jsonData];
}
}
// headers
if ((headers != nil) && (headers.count > 0)) {
[headers enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, NSString * _Nonnull obj, BOOL * _Nonnull stop) {
[request setValue:obj forHTTPHeaderField:key];
}];
}
// 顶层的POST,GET接口在JSON转换的过程中有问题,所以用更底层的dataTask接口;关键是自己组NSURLRequest,避开AFNetworking本身的坑
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; // 没有baseURL,在设置securityPolicy的时候会崩溃
// 执行dataTask
NSURLSessionDataTask *task = [manager dataTaskWithRequest:request uploadProgress:nil downloadProgress:nil completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
if (error == nil) {
if (success != nil) {
success(responseObject);
}
} else {
if (failure != nil) {
failure(error);
}
}
}];
// 启动任务
[task resume];
}
-
这种方式虽然麻烦了一点,但是胜在稳定可靠,没有明显的坑。
-
AFNetworking本身提供的JSON解析并不怎么样,还不如直接使用系统API,高效又简洁。
-
POST方式的body参数,有时候还是需要加解密的。用这种方式就可以操作了。
网友评论