对网络请求的封装 , 没有使用AFNetworking , 直接对原生的NSURLSession进行封装 , 功能比较简单 , 由于要封装一个包给别人用 , 如果我引入了AFNetworking , 别人也引入了 , 工程会报错 , 那我就对网络请求进行了简单的封装 .
1.参数的拼接 , 看过AFN的源码, AF会对参数的数组字典嵌套做处理, 但是我的网络请求很简单 , 参数中没有 数组字典的嵌套, 所以比较简单.
NSMutableArray * array = [[NSMutableArray alloc]initWithCapacity:self.parameters.count];
for (NSString * key in self.parameters) {
NSString * str = [NSString stringWithFormat:@"%@=%@",key,self.parameters[key]];
[array addObject:str];
}
NSString * body = [array componentsJoinedByString:@"&"];
request.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
2.服务器返回值的处理
由于服务器给的都是JSON , 没有xml之类的 , 所以直接JSON解析就行了, 但是JSON中服务器经常会带有NULL值,所以模仿AF做了一个去处NULL值的操作, 一开始写的对象方法, 但是看到AF使用了C函数 , 也照葫芦画瓢做成了C语言的
//8.解析数据
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSDictionary * result = dealWithDic(dic) ;
NSLog(@"\n~~~~~~~~~~~~http~success~~~~~~~~~~~~~~~~<<\nURL = %@\npara = %@ \n responseObject = %@\n >>~~~~~~~~~~~~http~end~~~~~~~~~~~~~~~~",self.urlString, self.parameters, result);
// 去掉 JSON字典/数组 里面的空值
id dealWithDic(id object) {
if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray * arr = [(NSArray *)object mutableCopy];
for (int i = (int)(arr.count-1); i>=0; i--) {
id value = arr[i];
if (value == nil || [value isKindOfClass:[NSNull class]]) {
[arr removeObjectAtIndex:i];
}
if ([value isKindOfClass:[NSArray class] ] || [value isKindOfClass:[NSDictionary class] ]) {
arr[i] = dealWithDic(value);
}
}
return arr;
}
if ([object isKindOfClass:[NSDictionary class] ]) {
NSMutableDictionary * result = [object mutableCopy];
for (NSString * key in object) {
id value = object[key];
if (value == nil || [value isKindOfClass:[NSNull class]]) {
[result removeObjectForKey:key];
}
if ([value isKindOfClass:[NSArray class] ] || [value isKindOfClass:[NSDictionary class] ]) {
result[key] = dealWithDic(value);
}
}
return result;
}
return object;
}
3.NSURLSessionDataTask的处理,系统提供了2种方式,一种是delegate的,一种是block的 , delegate的肯定功能更强大, AF就是用的代理 , 里面各种代理回调很多很细 , 但是我的需求很简单 , 不关系回调 , 只关心结果, 直接上block的 , 最终NetWork的文件.
#import <Foundation/Foundation.h>
typedef void(^callBackBlock)(id data);
@interface NetWork : NSObject
@property (nonatomic,copy) NSString * urlString ;
@property (nonatomic,strong) NSDictionary * parameters ;
@property (nonatomic,copy) callBackBlock success ;
@property (nonatomic,copy) callBackBlock fail ;
- (void)startLoadData ;
@end
#import "NetWork.h"
#define Safe_Block(block, ...) if (block) { block(__VA_ARGS__); };
@implementation NetWork
- (void)startLoadData{
if (self.urlString ==nil ) {
return;
}
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.urlString]];
request.HTTPMethod = @"POST";
NSMutableArray * array = [[NSMutableArray alloc]initWithCapacity:self.parameters.count];
for (NSString * key in self.parameters) {
NSString * str = [NSString stringWithFormat:@"%@=%@",key,self.parameters[key]];
[array addObject:str];
}
NSString * body = [array componentsJoinedByString:@"&"];
request.HTTPBody = [body dataUsingEncoding:NSUTF8StringEncoding];
NSURLSession * session = [NSURLSession sharedSession];
[session dataTaskWithRequest:request];
NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error) {
Safe_Block(self.fail,error);
return ;
}
//8.解析数据
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSDictionary * result = dealWithDic(dic) ;
NSLog(@"\n~~~~~~~~~~~~http~success~~~~~~~~~~~~~~~~<<\nURL = %@\npara = %@ \n responseObject = %@\n >>~~~~~~~~~~~~http~end~~~~~~~~~~~~~~~~",self.urlString, self.parameters, result);
Safe_Block(self.success,result);
}];
[task resume];
}
// 去掉 JSON字典/数组 里面的空值
id dealWithDic(id object) {
if ([object isKindOfClass:[NSArray class]]) {
NSMutableArray * arr = [(NSArray *)object mutableCopy];
for (int i = (int)(arr.count-1); i>=0; i--) {
id value = arr[i];
if (value == nil || [value isKindOfClass:[NSNull class]]) {
[arr removeObjectAtIndex:i];
}
if ([value isKindOfClass:[NSArray class] ] || [value isKindOfClass:[NSDictionary class] ]) {
arr[i] = dealWithDic(value);
}
}
return arr;
}
if ([object isKindOfClass:[NSDictionary class] ]) {
NSMutableDictionary * result = [object mutableCopy];
for (NSString * key in object) {
id value = object[key];
if (value == nil || [value isKindOfClass:[NSNull class]]) {
[result removeObjectForKey:key];
}
if ([value isKindOfClass:[NSArray class] ] || [value isKindOfClass:[NSDictionary class] ]) {
result[key] = dealWithDic(value);
}
}
return result;
}
return object;
}
@end
对了 , 由于控制台打印没有办法正确的显示中文,所以做了一个NSDictionary/NSArray的类别,方便打印中文的. 有了这个类别,直接在控制台看json,贼舒服
#import <Foundation/Foundation.h>
@interface NSArray (JsonLog)
@end
@interface NSDictionary (JsonLog)
@end
#import "NSDictionary+JsonLog.h"
@implementation NSArray (JsonLog)
- (NSString *)description{
if ( [NSJSONSerialization isValidJSONObject:self] ) {
NSData * data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil];
NSString * result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
result = [result stringByReplacingOccurrencesOfString:@"\\" withString:@""] ;
return result;
}
return [NSString stringWithFormat:@"%@",self];
}
@end
@implementation NSDictionary (JsonLog)
- (NSString *)description{
if ( [NSJSONSerialization isValidJSONObject:self] ) {
NSData * data = [NSJSONSerialization dataWithJSONObject:self options:NSJSONWritingPrettyPrinted error:nil];
NSString * result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
result = [result stringByReplacingOccurrencesOfString:@"\\" withString:@""] ;
return result;
}
return [NSString stringWithFormat:@"%@",self];
}
@end