学习制作iOS程序第八天:首页之本地缓存(26)

每次打开首页的时候都会有一个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或者刷新首页的话使用本地数据。如德芙般丝滑。

posted @ 2015-12-16 10:33  RandyTech  阅读(383)  评论(0编辑  收藏  举报