每次打开首页的时候都会有一个HUD的窗口在滚呀滚,而且程序进入后台后再次唤醒的时候还会滚呀滚。专业术语叫客户体验不好。
我们来为首页添加下本地缓存吧,常见的本地存储方式有四种。
1、NSKeyedArchiver:”采用归档的形式来保存数据,该数据对象需要遵守NSCoding协议,并且该对象对应的类必须提供encodeWithCoder:和initWithCoder:方法。前一个方法告诉系统怎么对对象进行编码,而后一个方法则是告诉系统怎么对对象进行解码。“
2、NSUserDefaults:”用来保存应用程序设置和属性、用户保存的数据。用户再次打开程序或开机后这些数据仍然存在。NSUserDefaults可以存储的数据类型包括:NSData、NSString、NSNumber、NSDate、NSArray、NSDictionary。如果要存储其他类型,则需要转换为前面的类型,才能用NSUserDefaults存储。"
3、Write写入方式:永久保存在磁盘中
4、SQLite:采用SQLite数据库来存储数据。SQLite作为一中小型数据库,应用ios中,跟前三种保存方式相比,相对比较复杂一些。还是一步步来吧!
我们使用FMDB。其实就是SQLite的另外一种表现形式而已。
二十六:利用FMDB实现首页的本地缓存
1、因为已经在Pods中下载FMDB的相应文件了。我们再PrefixMain.pcf文件中添加头文件的引用。
#import "FMDatabase.h" #import "FMDatabaseAdditions.h"
2、首页的.m文件中定义变量fmdb和bolUserCache,表示是否利用缓存加载数据。
@interface RDMainViewController ()<UIScrollViewDelegate,UITableViewDataSource,UITableViewDelegate, HttpHelperDelegate> { NSArray *arrMenuImage; NSArray *arrMenuText; UIView *btnbgview; RDHeaderView *headerview; UITableView *recommandTV; NSMutableArray *allhouse; HttpHelper *httpHelper; FMDatabase *fmdb; BOOL bolUseCache; } @end
3、我们利用NSUserDefaults保存数据库是否曾创建和初始化。名称为isDBInit
//20151214 为首页增加缓存功能,当时间很短或者网络不可用的时候直接调用缓存展示 //利用nsuserdefault判断是否创建过表,如果没有,创建一下 NSUserDefaults *userdefaults = [NSUserDefaults standardUserDefaults]; BOOL isDBInit = [userdefaults boolForKey:@"isDBInit"];
4、加载数据库并判断是否初始化,如果没有的话进行数据库的建立和初始化
NSString *doc =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; NSString *filename = [doc stringByAppendingPathComponent:@"fangwanjiadb.sqlite"]; fmdb = [FMDatabase databaseWithPath:filename]; if ([fmdb open]) { //如果正常打开了。判断是否需要初始化 if (isDBInit != YES) { //创建表TBSetup if ([fmdb tableExists:@"TBSetup"] == NO) { NSString *strsqlCreateTableSetup = @"CREATE TABLE TBSetup (SetupID INTEGER PRIMARY KEY AUTOINCREMENT, SetupName TEXT, SetupValue TEXT);"; [fmdb executeUpdate:strsqlCreateTableSetup]; } //插入一条数据 NSUInteger intTBSetupLastUpdateMainTime = [fmdb intForQuery:@"select count(*) from TBSetup where SetupName='LastUpdateMainTime';"]; if (intTBSetupLastUpdateMainTime<=0) { NSString *strsqlInsertLastUpdateTime = @"INSERT INTO TBSetup (SetupName, SetupValue) VALUES ('LastUpdateMainTime', '2000-1-1 00:00:00');"; [fmdb executeUpdate:strsqlInsertLastUpdateTime]; } //创建表tbhouselist if ([fmdb tableExists:@"TBHouseList"]==NO) { NSString *strsqlCreateTableHouseList = @"CREATE TABLE TBHouseList (AutoID INTEGER PRIMARY KEY AUTOINCREMENT,ShowType TEXT, HouseID INTEGER,HouseType TEXT,HouseTitle TEXT,HousePrice TEXT,HouseImage TEXT,CommInfo TEXT,HouseInfo TEXT,Feature1 TEXT,Feature2 TEXT,Feature3 TEXT);"; [fmdb executeUpdate:strsqlCreateTableHouseList]; } //NSString *strsqlCreateTableRentList = @""; //NSString *strsqlCreateTableProjList = @""; //bolResult = [fmdb executeUpdate:strsqlCreateTableRentList]; //bolResult = [fmdb executeUpdate:strsqlCreateTableProjList]; [userdefaults setBool:YES forKey:@"isDBInit"]; [userdefaults synchronize]; }
5、读取数据库,回去首页的最后更新时间,如果最后更新时间超过3分钟了,不使用缓存还是使用网络读取吧。
//查出数据判断是否已经更新过了 NSString *strLastUpdateTime = [fmdb stringForQuery:@"select SetupValue from TBSetup where SetupName='LastUpdateMainTime';"]; NSDate *lasttime = [ToolsHelper dateFromString:strLastUpdateTime]; NSDate *currtime = [NSDate date]; NSTimeInterval timeinteral = [currtime timeIntervalSinceDate:lasttime]; if ((int)timeinteral < 5 * 3) { //上次更新时间不超过3分钟,直接调用缓存吧,数据库类似于上一个。直接替换即可。 NSString *strQueryCache =@"select * from TBHouseList where ShowType='MainPageCache';"; FMResultSet *rs = [fmdb executeQuery:strQueryCache]; while ([rs next]) { HouseListModel *modhouse=[[HouseListModel alloc] init]; modhouse.HouseID = [rs intForColumn:@"HouseID"]; modhouse.HouseType = [rs stringForColumn:@"HouseType"]; modhouse.HouseTitle = [rs stringForColumn:@"HouseTitle"]; modhouse.HousePrice = [rs stringForColumn:@"HousePrice"]; modhouse.HouseImage = [rs stringForColumn:@"HouseImage"]; modhouse.CommInfo = [rs stringForColumn:@"CommInfo"]; modhouse.HouseInfo=[rs stringForColumn:@"HouseInfo"]; modhouse.Feature1=[rs stringForColumn:@"Feature1"]; modhouse.Feature2=[rs stringForColumn:@"Feature2"]; modhouse.Feature3=[rs stringForColumn:@"Feature3"]; [allhouse addObject:modhouse]; } bolUseCache = YES; } } //20151214 首页缓存功能,如果不用缓存才需要加载网络 if (bolUseCache == NO) { //初始化请求 httpHelper = [HttpHelper httpHelper]; httpHelper.delegate=self; [httpHelper GetMainPageRecommandHouseWithHUD:YES]; }
6、如果使用了缓存,需要重新设置tableview和scrollview的高度
//20151214 首页缓存功能 如果调用缓存,判断下frame if (bolUseCache == YES && allhouse.count>0) { CGRect tempframe = recommandTV.frame; tempframe.size.height = allhouse.count * floRowHeight-1.0f ; recommandTV.frame = tempframe; [_scrollview setContentSize:CGSizeMake(SCREEN_WIDTH, headerview.frame.origin.y + headerview.frame.size.height + allhouse.count * floRowHeight - 1.0f)]; }
7、其他改动之一、当利用网络读取数据并成功返回的时候,重新写入数据库,并且更新最后获取的时间,卸载initDataWithDict:(NSDictionary *)dict方法里了。
//20151214 首页缓存功能 插入完毕后 更新最后更新时间 清空原数据库 if ([fmdb open]) { [fmdb executeUpdate:@"delete from TBHouseList where ShowType='MainPageCache';"]; [fmdb executeUpdate:@"update TBSetup set SetupValue=? where SetupName='LastUpdateMainTime';",[ToolsHelper stringFromDate:[NSDate date]]]; }
//20151214 首页缓存功能 加载完毕后保存到缓存 if ([fmdb open]) { //插入数据到数据库 NSString *strInsertHouseList = @"INSERT INTO TBHouseList (ShowType, HouseID, HouseType, HouseTitle, HousePrice, HouseImage, CommInfo, HouseInfo, Feature1, Feature2, Feature3) VALUES('MainPageCache',?,?,?,?,?,?,?,?,?,?);"; [fmdb executeUpdate:strInsertHouseList,[NSNumber numberWithLong:modhouse.HouseID],modhouse.HouseType,modhouse.HouseTitle,modhouse.HousePrice,modhouse.HouseImage,modhouse.CommInfo,modhouse.HouseInfo,modhouse.Feature1,modhouse.Feature2,modhouse.Feature3]; }
8、viewWillDisappear稍作改动
#pragma mark - 隐藏hud和网络 -(void)viewWillDisappear:(BOOL)animated { //20151214 首页缓存功能 调用网络的时候才需要执行此方法 if (bolUseCache == NO) { [[HttpHelper httpHelper] CancelAllRequest]; [ToolsHelper CloseHUD]; } self.navigationController.navigationBar.hidden=NO; [super viewWillDisappear:animated]; }
这样就实现了本地缓存功能,首次打开首页的时候加载数据并保存到数据库。
三分钟之内再次打开app或者刷新首页的话使用本地数据。如德芙般丝滑。