• 学习制作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或者刷新首页的话使用本地数据。如德芙般丝滑。

  • 相关阅读:
    C#使用表达式树实现对象复制
    用vbs将字符串复制到剪贴板
    C# 动态获取程序集信息
    关于ftp的主动模式(Active Mode)和被动模式(Passive Mode)
    %userprofile%\Local Settings文件夹拒绝访问怎么办
    在Winform框架的多文档界面中实现双击子窗口单独弹出或拖出及拽回的处理
    ABP VNext框架基础知识介绍(1)框架基础类继承关系
    ABP开发框架中分页查询排序的实现处理
    Vue&Element开发框架中增加工作流处理,工作流的各个管理页面的界面处理
    基于ABP开发框架的技术点分析和项目快速开发实现
  • 原文地址:https://www.cnblogs.com/randytech/p/5044582.html
Copyright © 2020-2023  润新知