准备工作:
- 先导入运用到的第三方库AFNetWorking、YYCache
- 新建一个类,继承于NSObject
- 写一个请求方法的枚举:
typedef NS_ENUM(NSUInteger, RequestType) {
POST,
GET
};
4.写回调方法:
/** 成功的回调 */
typedef void(^SuccessBlock)(NSDictionary *responseObject,NSString *msg);
/** 失败的回调 */
typedef void(^FailedBlock)(NSError *error,NSString *msg);
5.创建单例:
/**
单例
@return return value description
*/
+ (NetRequest *)shareInstance;
6.请求方法:
/**
请求数据
@param requestType 请求方式
@param URLString URLString
@param parameters 请求参数
@param isCache 是否缓存
@param cacheKey 从缓存中取数据的关键词
@param successBlock 成功回调
@param failedBlock 失败回调
*/
- (void)requestWithMethod:(RequestType)requestType URLString:(NSString *)URLString parameters:(NSDictionary *)parameters isCache:(BOOL)isCache cacheKey:(NSString *)cacheKey success:(SuccessBlock)successBlock failed:(FailedBlock)failedBlock;
以上的都是在.h中声明,接下来是重头戏,.m文件中的具体实现,直接代码走起:
#import "NetRequest.h"
#import "AFNetworking.h"
#import "YYCache.h"
NSString * const NetCache = @"NetCache";
@implementation NetRequest
+ (NetRequest *)shareInstance{
static NetRequest *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc]init];
});
return instance;
}
- (void)requestWithMethod:(RequestType)requestType URLString:(NSString *)URLString parameters:(NSDictionary *)parameters isCache:(BOOL)isCache cacheKey:(NSString *)cacheKey success:(SuccessBlock)successBlock failed:(FailedBlock)failedBlock{
//处理中文和空格问题
URLString = [URLString stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//拼接
NSString * cacheUrl = [self urlDictToStringWithUrlStr:URLString WithDict:parameters];
YYCache *cache = [[YYCache alloc]initWithName:NetCache];
cache.memoryCache.shouldRemoveAllObjectsOnMemoryWarning = YES;
cache.memoryCache.shouldRemoveAllObjectsWhenEnteringBackground = YES;
id cacheData;
if (isCache) {
//根据网址从Cache中取数据
cacheData = [cache objectForKey:cacheKey];
if (cacheData != 0) {
//将数据统一处理
[self returnDataWithRequestData:cacheData Success:^(NSDictionary *responseObject, NSString *msg) {
successBlock(responseObject,msg);
} failure:^(NSError *error, NSString *msg) {
failedBlock(error,msg);
}];
}
}
//进行网络检查
if (![self requestBeforeJudgeConnect]) {
failedBlock(nil,@"没有网络");
return;
}
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/json",@"text/javascript",@"text/html", nil];
manager.requestSerializer.timeoutInterval = 10;
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
__weak typeof(self)weakSelf = self;
if (requestType == POST) {
[manager POST:URLString parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[weakSelf dealWithResponseObject:responseObject cacheUrl:cacheUrl cacheData:cacheData isCache:isCache cache:cache cacheKey:cacheKey success:^(NSDictionary *responseObject, NSString *msg) {
successBlock(responseObject,msg);
} failure:^(NSError *error, NSString *msg) {
failedBlock(error,msg);
}];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failedBlock(error,@"出错了");
}];
}
if (requestType == GET) {
[manager GET:URLString parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
[weakSelf dealWithResponseObject:responseObject cacheUrl:cacheUrl cacheData:cacheData isCache:isCache cache:cache cacheKey:cacheKey success:^(NSDictionary *responseObject, NSString *msg) {
successBlock(responseObject,msg);
} failure:^(NSError *error, NSString *msg) {
failedBlock(error,msg);
}];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
failedBlock(error,@"出错了");
}];
}
}
#pragma mark - 网络判断
-(BOOL)requestBeforeJudgeConnect
{
struct sockaddr zeroAddress;
bzero(&zeroAddress, sizeof(zeroAddress));
zeroAddress.sa_len = sizeof(zeroAddress);
zeroAddress.sa_family = AF_INET;
SCNetworkReachabilityRef defaultRouteReachability =
SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
SCNetworkReachabilityFlags flags;
BOOL didRetrieveFlags =
SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
CFRelease(defaultRouteReachability);
if (!didRetrieveFlags) {
printf("Error. Count not recover network reachability flags\n");
return NO;
}
BOOL isReachable = flags & kSCNetworkFlagsReachable;
BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
BOOL isNetworkEnable =(isReachable && !needsConnection) ? YES : NO;
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible =isNetworkEnable;/* 网络指示器的状态: 有网络 : 开 没有网络: 关 */
});
return isNetworkEnable;
}
#pragma mark - 根据返回的数据进行统一的格式处理 ----requestData 网络或者是缓存的数据----
- (void)returnDataWithRequestData:(NSData *)requestData Success:(SuccessBlock)success failure:(FailedBlock)failure{
id myResult = [NSJSONSerialization JSONObjectWithData:requestData options:NSJSONReadingMutableContainers error:nil];
//判断是否为字典
if ([myResult isKindOfClass:[NSDictionary class]]) {
NSDictionary * requestDic = (NSDictionary *)myResult;
//根据返回的接口内容来变,这里不是固定的,根据具体返回的内容具体定
NSString * succ = [NSString stringWithFormat:@"%@",requestDic[@"status"]];
if ([succ isEqualToString:@"1"]) {
success(requestDic,@"成功了");
}else{
failure(nil,@"失败了");
}
}
}
#pragma mark - 统一处理请求到的数据
-(void)dealWithResponseObject:(NSData *)responseData cacheUrl:(NSString *)cacheUrl cacheData:(id)cacheData isCache:(BOOL)isCache cache:(YYCache*)cache cacheKey:(NSString *)cacheKey success:(SuccessBlock)success failure :(FailedBlock)failure
{
dispatch_async(dispatch_get_main_queue(), ^{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;// 关闭网络指示器
});
NSString * dataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
dataString = [self deleteSpecialCodeWithStr:dataString];
NSData *requestData = [dataString dataUsingEncoding:NSUTF8StringEncoding];
if (isCache) {
//
[cache setObject:requestData forKey:cacheKey];
}
//如果不缓存 或者 数据不相同 从网络请求
if (!isCache || ![cacheData isEqual:requestData]) {
[self returnDataWithRequestData:requestData Success:^(NSDictionary *requestDic, NSString *msg) {
success(requestDic,msg);
} failure:^(NSError *error,NSString *msg) {
failure(error,msg);
}];
}
}
#pragma mark - 拼接post请求的url
-(NSString *)urlDictToStringWithUrlStr:(NSString *)urlStr WithDict:(NSDictionary *)parameters
{
if (!parameters) {
return urlStr;
}
NSMutableArray *parts = [NSMutableArray array];
[parameters enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id _Nonnull obj, BOOL * _Nonnull stop) {
//接收key
NSString *finalKey = [key stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
//接收值
NSString *finalValue = [obj stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];
NSString *part =[NSString stringWithFormat:@"%@=%@",finalKey,finalValue];
[parts addObject:part];
}];
NSString *queryString = [parts componentsJoinedByString:@"&"];
queryString = queryString ? [NSString stringWithFormat:@"?%@",queryString] : @"";
NSString *pathStr = [NSString stringWithFormat:@"%@?%@",urlStr,queryString];
return pathStr;
}
#pragma mark - 处理json格式的字符串中的换行符、回车符
- (NSString *)deleteSpecialCodeWithStr:(NSString *)str {
NSString *string = [str stringByReplacingOccurrencesOfString:@"\r" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"\n" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"\t" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@" " withString:@""];
string = [string stringByReplacingOccurrencesOfString:@"(" withString:@""];
string = [string stringByReplacingOccurrencesOfString:@")" withString:@""];
return string;
}
@end
以上内容在下亲测,完美运行,没有问题。如若哪位大神不幸看到了问题,请不吝赐教!