资讯专栏INFORMATION COLUMN

IOS开发之离线缓存方案

siberiawolf / 874人阅读

摘要:离线缓存有多种方案,一什么是离线缓存离线缓存就是把用户访问过的数据存到本地的数据库中,下次打开时首先展示上次查阅过得数据如同微信,然后再刷新请求网络获取新的数据。

离线缓存有多种方案,

一.什么是离线缓存?

离线缓存就是把用户访问过的数据存到本地的数据库中,下次打开App时首先展示上次查阅过得数据(如同微信),然后再刷新请求网络获取新的数据。

以新浪微博请求网络流程图为例:

思考一个问题,本地缓存需要创建多少张表,保存哪些内容呢?以新浪微博的一条微博为例:

第一种思路:

设计三张表,用户表,微博内容表,图片表(包含缩略图、中等图、大图等)

第二种思路:

为了简单,只用一张表,将服务器接口所返回的json数据直接存入表中,用的时候只需从表中解析即可 。

表结构设计:

access_token:一个access_token代表一个账号,如果一个用户有多个账号,则每个账号对应不同的缓存数据,即用来处理多账号登陆的问题。

二.离线缓存项目中实现

第一次网络请求后,存在缓存,下次进入后直接从缓存中获取数据。

//  IWStatusTool.m
//  ItcastWeibo
//
//  Created by kaiyi on 16-6-3.
//  Copyright (c) 2016年 itcast. All rights reserved.

#import "IWStatusCacheTool.h"

+(void)homeStatusesWithParam:(IWHomeStatusesParam *)param success:(void (^)(IWHomeStatusesResult *))success failure:(void (^)(NSError *))failure
{
    // 1.先从缓存里边加载
    NSArray *dicArray = [IWStatusCacheTool statuesWithParam:param];
    if(dicArray.count){ // 有缓存
        // 传递了block
        if (success) {
            IWHomeStatusesResult *result = [[IWHomeStatusesResult alloc] init];
            
            result.statuses = [IWStatus objectArrayWithKeyValuesArray:dicArray];
            
            success(result);
        }
    }
    else
    {
        [IWHttpTool getWithURL:@"https://api.weibo.com/2/statuses/home_timeline.json" params:param.keyValues success:^(id json)
         {
             // 缓存 -[2016-07-09 add]
             [IWStatusCacheTool addStatuses:json[@"statuses"]];
             // NSArray *dictArray = json[@"status"];
             
             
             // 请求成功后,新浪返回类型为字典的json,这里需要将字典转为模型
             if(success){
                 IWHomeStatusesResult *result = [IWHomeStatusesResult objectWithKeyValues:json];
                 
                 success(result);
             }
             
         } failure:^(NSError *error) {
             if(failure){
                 failure(error);
             }
         }];

        
    }
}

封装一个离线cache的工具类:
IWStatusCacheTool.m

//
//  IWStatusCacheTool.m
//  ItcastWeibo
//
//  Created by kaiyi on 16-7-9.
//  Copyright (c) 2016年 itcast. All rights reserved.
//

#import "IWStatusCacheTool.h"
#import "IWAccount.h"
#import "IWAccountTool.h"
#import "FMDB.h"

@implementation IWStatusCacheTool

static FMDatabaseQueue *_queue;

+(void)initialize{
    
    // 0.获得沙盒中的数据库文件名
    NSString *path = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"statuses.sqlite"];
    
    // 1.创建队列
    _queue =  [FMDatabaseQueue databaseQueueWithPath:path];
    
    // 2.创表
    [_queue inDatabase:^(FMDatabase *db) {
        [db executeUpdate:@"create table if not exists t_status (id integer primary key autoincrement, access_token text, idstr text, dict blob);"];
    }];
}

+(void)addStatus:(NSDictionary *)dict
{
    [_queue inDatabase:^(FMDatabase *db) {
        NSString *accessToken = [IWAccountTool account].access_token;
        NSString *idstr = dict[@"idstr"];
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict];
        [db executeUpdate:@"insert into t_status (access_token, idstr, dict) values(?,?,?)", accessToken, idstr, data];
    }];
   
    
}

+(void)addStatuses:(NSArray *)dictArray
{
    for(NSDictionary *dict in dictArray){
        [self addStatus:dict];
    }
    
    
}



+(NSArray *)statuesWithParam:(IWHomeStatusesParam *)param
{
    // 1.定义数组
    __block NSMutableArray *dictArray = nil;
    
    // 2.使用数据库
    [_queue inDatabase:^(FMDatabase *db) {
        
        // 创建数组
        dictArray = [NSMutableArray array];
        
        // accessToken
         NSString *accessToken = [IWAccountTool account].access_token;
        
        FMResultSet *rs = nil;
        if (param.since_id) { // 如果有since_id
            rs = [db executeQuery:@"select * from t_status where access_token = ? and idstr > ? order by idstr desc limit 0,?;", accessToken, param.since_id, param.count];
        } else if (param.max_id) { // 如果有max_id
            rs = [db executeQuery:@"select * from t_status where access_token = ? and idstr <= ? order by idstr desc limit 0,?;", accessToken, param.max_id, param.count];
        } else { // 如果没有since_id和max_id
            rs = [db executeQuery:@"select * from t_status where access_token = ? order by idstr desc limit 0,?;", accessToken, param.count];
        }

        
        while(rs.next){
            NSData *data = [rs dataForColumn:@"dict"];
            NSDictionary *dict = [NSKeyedUnarchiver unarchiveObjectWithData:data];
            [dictArray addObject:dict];
        }
    }];
    
    return dictArray;
}

@end

项目源代码,请访问github获取微博项目源代码github

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/16334.html

相关文章

  • 移动端本地 H5 秒开方案探索与实现

    摘要:然而这样的方案实现起来十分繁琐,原因是资源给到客户端打包时很分散,不统一,管理困难。上述讨论的仅针对功能模块类的单页面页面秒开的优化方案,其他一些交互较复杂的页面可能并不适用,还需要视实际情况和需求而定。 欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 企业微信移动端项目中有需求要展示数据趋势的可视化图表,经过调研,最终决定以单页面 H5 来完成,对 APP 里的一些使用 ...

    snowell 评论0 收藏0
  • Web离线技术(一)—— 技术选型

    摘要:上面提到在安卓完全不需要像这样大费周章的绕弯路,所以安卓可能就不需要这个自定义的,这样又会导致面临着与安卓差异化严重问题。前言 最早接触离线包的概念要追溯到16年初,项目迎来大改版,其中重点项目之一就是离线包方案的制定与实施。离线包顾名思义就是将H5/CSS/JS和资源文件打包提前下发到App中,这样App在加载网页的时候实际上加载的是本地的文件,减少网络请求来提高网页的渲染速度,并实现动态...

    null1145 评论0 收藏0
  • 让老板虎躯一震的前端技术,KPI杀手

    摘要:我们的目标是让的页面也能够拥有般的体验,如果你还在寻求什么技术能够让老板虎躯一震拯救你的,那么这篇文章或许能够帮助到你。这是一个使用编写的页面,运行于多端,包括企鹅辅导手机手机浏览器。经过我们的测试发现安卓基本上都是支持的,需要以上才支持。 本文由云+社区发表作者:思衍Jax showImg(https://segmentfault.com/img/remote/1460000017...

    PiscesYE 评论0 收藏0
  • 让老板虎躯一震的前端技术,KPI杀手

    摘要:我们的目标是让的页面也能够拥有般的体验,如果你还在寻求什么技术能够让老板虎躯一震拯救你的,那么这篇文章或许能够帮助到你。这是一个使用编写的页面,运行于多端,包括企鹅辅导手机手机浏览器。经过我们的测试发现安卓基本上都是支持的,需要以上才支持。 本文由云+社区发表 作者:思衍Jax 天下武功,唯 (wei) 快(fu) 不(bu) 破(po)。 随着近几年的前端技术的高速发展,越来越多的...

    Jaden 评论0 收藏0
  • 让老板虎躯一震的前端技术,KPI杀手

    摘要:我们的目标是让的页面也能够拥有般的体验,如果你还在寻求什么技术能够让老板虎躯一震拯救你的,那么这篇文章或许能够帮助到你。这是一个使用编写的页面,运行于多端,包括企鹅辅导手机手机浏览器。经过我们的测试发现安卓基本上都是支持的,需要以上才支持。 本文由云+社区发表作者:思衍Jax showImg(https://segmentfault.com/img/remote/1460000017...

    ingood 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<