标签:
// 首先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
// 该方法的执行逻辑,如下: - (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; }
YTKNetwork系列之-----YTKRequest缓存ResponseData实现
标签:
原文地址:http://www.cnblogs.com/xiongzenghui/p/4625672.html