iOS 带缓存,带网络监控的数据请求

准备工作:

  1. 先导入运用到的第三方库AFNetWorking、YYCache
  2. 新建一个类,继承于NSObject
  3. 写一个请求方法的枚举:
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

以上内容在下亲测,完美运行,没有问题。如若哪位大神不幸看到了问题,请不吝赐教!

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值