YTKNetwork详解(三)

YTKRequest缓存ResponseData实现

一、YTKRequest继承自YTKBaseRequest类,用于单独封装所有responseData缓存代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 首先YTKRequest的代码如下:
 
@interface  YTKRequest : YTKBaseRequest
 
//表示当前请求,是否忽略本地缓存responseData
@property  ( nonatomic BOOL  ignoreCache;
 
/// 返回当前缓存的对象
- ( id )cacheJson;
 
/// 是否当前的数据从缓存获得
- ( BOOL )isDataFromCache;
 
/// 返回是否当前缓存需要更新【缓存是否超时】
- ( BOOL )isCacheVersionExpired;
 
/// 强制更新缓存【不使用缓存数据】
- ( void )startWithoutCache;
 
/// 手动将其他请求的JsonResponse写入该请求的缓存
- ( void )saveJsonResponseToCacheFile:( id )jsonResponse;
 
/// 子类重写方法【参数方法】
- ( NSInteger )cacheTimeInSeconds;     //当前请求指定时间内,使用缓存数据
- ( long  long )cacheVersion;     //当前请求,指定使用版本号的缓存数据
- ( id )cacheSensitiveData;    
 
@end
    

  

二、然后从YTKRequest的start方法看起,这个方法表示开始执行请求

复制代码
// 该方法的执行逻辑,如下:

- (void)start {

    //1. 当前请求,是否忽略缓存数据 
    if (self.ignoreCache) {
        [super start];
        return;
    }

    //2. 当前请求,是否设置了缓存超时时间
    if ([self cacheTimeInSeconds] < 0) {
        [super start];
        return;
    }

    //3. 当前请求,对应的本地缓存数据的版本号,是否与当前请求指定的版本号一致
    long long cacheVersionFileContent = [self cacheVersionFileContent];
    if (cacheVersionFileContent != [self cacheVersion]) {
        [super start];
        return;
    }

    //4. 当前请求,本地是否存在缓存数据文件
    NSString *path = [self cacheFilePath];
    NSFileManager *fileManager = [NSFileManager defaultManager];
    if (![fileManager fileExistsAtPath:path isDirectory:nil]) {
        [super start];
        return;
    }

    //5. 当前请求,对应的缓存数据,是否已经超时
    int seconds = [self cacheFileDuration:path];
    if (seconds < 0 || seconds > [self cacheTimeInSeconds]) {
        [super start];
        return;
    }

    //6. 当前请求,对应的本地缓存数据文件,是否能够取到responseJSON
    _cacheJson = [NSKeyedUnarchiver     unarchiveObjectWithFile:path];
    if (_cacheJson == nil) {
        [super start];
        return;
    }

    //7. 如果以上情况,都不满足,表示本次请求的数据,来自本地缓存
    _dataFromCache = YES;
     
    //8. 结束本次请求,执行回调Block,释放Block
    [self requestCompleteFilter];

    YTKRequest *strongSelf = self;
    [strongSelf.delegate requestFinished:strongSelf];
    if (strongSelf.successCompletionBlock) {
        strongSelf.successCompletionBlock(strongSelf);
    }
    [strongSelf clearCompletionBlock];
}
复制代码

 

三、本地缓存数据文件的管理方式:

管理方式一、按版本号

复制代码
注意: 将一个responseJSON保存到本地,会同时产生2个文件
》文件一:保存responseData的文件
》文件二:标识本地保存responseData的版本号

//1. 得到responseJSON的缓存文件名

- (NSString *)cacheFileName {
    NSString *requestUrl = [self requestPath];
    NSString *baseUrl = nil;
    if ([self baseURLType] == ZSYBaseURLBasic) {
        baseUrl = [YTKNetworkConfig sharedInstance].basicBaseUrl;
    } else if ([self baseURLType] == ZSYBaseURLWealthManagement) {
        baseUrl = [YTKNetworkConfig sharedInstance].cashBaseUrl;
    }
    id argument = [self cacheFileNameFilterForRequestArgument:[self requestArgument]];
    NSString *requestInfo = [NSString stringWithFormat:@"Method:%ld Host:%@ Url:%@ Argument:%@ AppVersion:%@ Sensitive:%@",
                                                        (long)[self requestMethod], baseUrl, requestUrl,
                                                        argument, [YTKNetworkPrivate appVersionString], [self cacheSensitiveData]];
    NSString *cacheFileName = [YTKNetworkPrivate md5StringFromString:requestInfo];
    return cacheFileName;
}

//2. 2个缓存文件的全路径 
//文件一: 手机沙盒Document/LazyRequestCache/缓存文件名
//文件二: 手机沙盒Document/LazyRequestCache/缓存文件名.version

- (NSString *)cacheFilePath {
    NSString *cacheFileName = [self cacheFileName];
    NSString *path = [self cacheBasePath];
    path = [path stringByAppendingPathComponent:cacheFileName];
    return path;
}

//3. 读取版本号文件中保存的NSNumber值

- (long long)cacheVersionFileContent {
    NSString *path = [self cacheVersionFilePath];
    NSFileManager * fileManager = [NSFileManager defaultManager];
    if ([fileManager fileExistsAtPath:path isDirectory:nil]) {
        NSNumber *version = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
        return [version longLongValue];
    } else {
        return 0;//默认版本号=0
    }
}

//4. 当前请求指定的版本号 与 本地缓存文件保存的版本号 ,对比后如果一致表示是合法缓存数据,否则是不合法缓存数据

long long cacheVersionFileContent = [self cacheVersionFileContent];
    if (cacheVersionFileContent != [self cacheVersion]) {
        [super start];
        return;
    }

//5. 保存从服务器获取到的responseJSON按版本号

- (void)saveJsonResponseToCacheFile:(id)jsonResponse {

    //1. 当前请求设置过缓存超时--》使用缓存
    //2. responseJSON不是来自本地缓存文件
    if ([self cacheTimeInSeconds] > 0 && ![self isDataFromCache]) {
        NSDictionary *json = jsonResponse;
        if (json != nil) {

            //保存responseJSON
            [NSKeyedArchiver archiveRootObject:json toFile:[self cacheFilePath]];

            //保存当前request指定的版本号
            [NSKeyedArchiver archiveRootObject:@([self cacheVersion]) toFile:[self cacheVersionFilePath]];
        }
    }
}
复制代码

 

管理方式二、按超时时间

复制代码
/**
 *
 * 核心:
 *      通过本地文件,创建时间 与 当前操作时间,的时间差,是否超过指定的时间长度
 *
 */

- (int)cacheFileDuration:(NSString *)path {
    NSFileManager *fileManager = [NSFileManager defaultManager];
    // get file attribute
    NSError *attributesRetrievalError = nil;
    NSDictionary *attributes = [fileManager attributesOfItemAtPath:path
                                                             error:&attributesRetrievalError];
    if (!attributes) {
        YTKLog(@"Error get attributes for file at %@: %@", path, attributesRetrievalError);
        return -1;
    }
    int seconds = -[[attributes fileModificationDate] timeIntervalSinceNow];
    return seconds;
}


int seconds = [self cacheFileDuration:path];
    if (seconds < 0 || seconds > [self cacheTimeInSeconds]) {
        [super start];
        return;
    }
复制代码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值