上个项目的一些反思 III
离线缓存
之前的项目因为实时性要求比较高,所以一打开客户端,就开始做网络请求.现在想想,是没有做内容的离线缓存.这个问题,我没意识到.产品经理也没有意识到...
我觉得Archiver,来做比较合适,可复写.可直接从存储中读取model,(当然要在相应的model里实现NSCoding协议)代码如下
#pragma mark ============实现NSCoding协议 //归档 - (void)encodeWithCoder:(NSCoder *)Coder { NSDate * senddate=[NSDate date]; NSDateFormatter *dateformatter=[[NSDateFormatter alloc] init]; [dateformatter setDateFormat:@"YYYY-MM-dd,hh:mm:ss"]; NSString *str = [NSString stringWithFormat:@"Cached@:%@",[dateformatter stringFromDate:senddate]]; [Coder encodeObject:_citynm forKey:@"CityName"]; [Coder encodeObject:_weather forKey:@"Weather"]; [Coder encodeObject:_temperature_curr forKey:@"NowTemp"]; [Coder encodeObject:str forKey:@"days"]; [Coder encodeObject:UIImagePNGRepresentation(_Logo) forKey:@"img"]; } //解档 - (nullable instancetype)initWithCoder:(NSCoder *)Decoder // NS_DESIGNATED_INITIALIZER { if (self = [super init]) { self.citynm = [Decoder decodeObjectForKey:@"CityName"]; self.weather = [Decoder decodeObjectForKey:@"Weather"]; self.temperature_curr = [Decoder decodeObjectForKey:@"NowTemp"]; self.days = [Decoder decodeObjectForKey:@"days"]; self.Logo = [UIImage imageWithData:[Decoder decodeObjectForKey:@"img"]]; } return self; }
Archiver的封装
#import <Foundation/Foundation.h> @interface ArchiverCache : NSObject /** * 归档 * * @param model model * @param Key Key */ -(void)EncoderDoWithModel:(id)model withKey:(NSString*)Key; /** * 反归档 * * @param Key * * @return (id)Model */ -(id)UncoderDoWith:(NSString*)Key; @end ====================.M================= #import "ArchiverCache.h" @implementation ArchiverCache //archiver -(void)EncoderDoWithModel:(id)model withKey:(NSString *)Key { NSMutableData *data = [[NSMutableData alloc] init]; //创建归档辅助类 NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; //编码 [archiver encodeObject:model forKey:Key]; //结束编码 [archiver finishEncoding]; //写入 if ([data writeToFile:[self GetFilePath] atomically:YES]) { NSLog(@"Cache Set Success"); }else{ NSLog(@"Cache Set Fail"); } } //Unarchiver -(id)UncoderDoWith:(NSString *)Key { ///////////////////////解档 NSData *_data = [[NSData alloc] initWithContentsOfFile:[self GetFilePath]]; //解档辅助 NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:_data]; //解码并解档出model id Wm = [unarchiver decodeObjectForKey:Key]; //关闭解档 [unarchiver finishDecoding]; return Wm; } -(NSString *)GetFilePath { NSArray *arr = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); //虽然该方法返回的是一个数组,但是由于一个目标文件夹只有一个目录,所以数组中只有一个元素。 NSString *cachePath = [arr lastObject]; NSString *filePath = [cachePath stringByAppendingPathComponent:@"Model"]; // NSLog(@"%@",filePath); return filePath; } @end
调用,在这个例子里,每次进行model操作的时候,都会直接进行归档操作.这样可以保持归档里的数据都是最新的.
-(id)NetViewModelWithCache { //读取缓存... ArchiverCache *ar = [[ArchiverCache alloc] init]; //需在相应的model实现 initWithCoder; WeatherModel *Wm = [ar UncoderDoWith:@"weather"]; return Wm; } -(id)ConvertToModel:(id)Data { WeatherModel *model = [[WeatherModel alloc] initWithDictionary:Data]; ///转成模型,同时把IMG给下载了.....由于API里的ICON是GIF,为了省事,这里直接另找了一张图.(可用sdwebimage来处理gif) NSString *imageURLStr = @"http://pic.58pic.com/58pic/15/48/73/04f58PIC37y_1024.png"; NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL URLWithString:imageURLStr]]; model.Logo = [UIImage imageWithData:imageData]; ArchiverCache *ar = [[ArchiverCache alloc] init]; //需在相应的model实现 encodeWithCoder; [ar EncoderDoWithModel:model withKey:@"weather"]; return model; }