码迷,mamicode.com
首页 > 移动开发 > 详细

IOS开发中关于数据的本地化存储

时间:2015-12-19 00:14:26      阅读:362      评论:0      收藏:0      [点我收藏+]

标签:

对于IOS开发者而言, 项目中数据的本地化存储,最难的一点,莫过于SQL语句的编写,除此之外, 其实也没什么难度, 当然在创建数据库之前,我们必须要做的是对数据进行分析, 然后对FMDB进行简单的封装:

代码如下:

#import "SQLiteManger.h"

#import "FMDB.h"

@interface SQLiteManger ()

@end

 

@implementation SQLiteManger

/// 创建一个单例单例

+(instancetype)shareSQLiteManger{

    static id instance;

    static dispatch_once_t onceToken;

    dispatch_once(&onceToken, ^{

        instance = [[self alloc] init];

    }); 

    return instance;

}

 

// 重写init

-(instancetype)init{ 

    // 数据路路径

    NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;

    path = [path stringByAppendingPathComponent:@"meifangwang.db"];

    NSLog(@"路径是:%@",path);

    

    // 打开数据库,没有则创建一个数据库

    FMDatabaseQueue *queue = [FMDatabaseQueue databaseQueueWithPath:path];    

    self.queue = queue;

    [self creatTable];

    return self;

}

 

//建表

-(void)creatTable {

 

    // SQL执行语句路径

    NSString *path = [[NSBundle mainBundle] pathForResource:@"db.sql" ofType:nil];

    NSString *sql = [NSString stringWithContentsOfFile:path];

 

    // 执行SQL语句

    [self.queue inDatabase:^(FMDatabase *db) {       

        if ([db executeStatements:sql]){

            NSLog(@"建表成功");

        }else{

            NSLog(@"建表失败");

        }

    }];

}

 

// 查询

-(NSMutableArray *)execRecordSet:(NSString *)sql{

    // 定义一个数组

    NSMutableArray * array = [[NSMutableArray alloc ] init];    

    // `同步`执行数据库查询 - FMDB 默认情况下,都是在主线程上执行的

    [[SQLiteManger shareSQLiteManger].queue inDatabase:^(FMDatabase *db) { 

        FMResultSet *rs = [db executeQuery:sql];

        while ([rs next]) {  

            //列数

            int colCount = rs.columnCount;

            

            //字典

            NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];

            

            // 遍历

            for (int i = 0; i < colCount; i++) {

                

                // 列名

                NSString *name = [rs columnNameForIndex:i];

                

                // 值

               NSObject * obj = [rs objectForColumnIndex:i];

                

                // 设置字典

                dict[name] = obj;

            }

            [array addObject:dict];

        }

    }];

    

    return array;

@end

 

相关SQL语句 --> 当然我们建表的SQL语句个人建议单独写在一个文件夹中

CREATE TABLE IF NOT EXISTS "T_Showroom" (

"houseId" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,

"hourseInfo" TEXT,

"userId" INTEGER

);

1.进行数据结构(数据表)的设计, 

eg: 1> 主键的标示

  2> 对应房子的完整的数据

  3> 当前登陆账户的userId

 

2. 数据访问层模型的设计

数据访问层(DAL):专门负责处理本地SQLite和网络数据查看本地是否有数据,  有, 直接返回数据, 没有网络中加载  

1>加载相关数据  --- > 根据工作需要做适当的调整

  1>> 检查本地是否缓存数据 

  2>>  如果有返回数据

  3>> 如果没有,加载网络数据 

  4>> 将网络返回的数据,保存在本地,一边后续使用

  5>> 返回网络数据

2> 保存网络数据(saveCacheData)  —> 上面调用

  1> 参数

    定义一个数据array 记录网络返回的字典数组

  2>  编写SQL语句, 根据SQL语句确认参数,  _houseId, 网络数据序列化,用户ID

  3>   获取要插入数据库的数据:_houseId,用户ID   网络数据序列化(序列化字典 —> 二进制数据)

  4> 执行SQL语句, 插入 

3> 检查本地是否已有数据—> 1中调用

  1> 参数: 

  2> 编写SQL,并测试SQL

  3>   执行SQL语句, 返回数据集合

4整合本地缓存数据和网络数据方法

5> 满足一定条件时,清除缓存  

        1>> 清理缓存工作,千万不要交给用户使用!

        2>> 一定要定期清理数据库的缓存,原因

          - SQLite 的数据库,随着数据的增加,会不断的变大

          - 但是:如果删除了数据,数据库不会变小!SQLite 认为,既然数据库会涨到这么大,留出空间,准备下一次涨到这么大

            - SQLite不会再额外分配磁盘空间

        - 一般不会把 图片/音频/视频 放在数据库中,不便于检索,占用磁盘空间很大!

eg: swift版定期清除本地数据:

  /// 最大缓存时间

  private let maxCacheDateTime: NSTimeInterval = 60 // 7 * 24 * 60 * 60

    class func clearDataCache() {

        

        // 1. 准备日期

        let date = NSDate(timeIntervalSinceNow: -maxCacheDateTime)

        

        // 日期格式转换

        let df = NSDateFormatter()

        // 指定区域 - 在模拟器不需要,但是真机一定需要

        df.locale = NSLocale(localeIdentifier: "en")

        // 指定日期格式

        df.dateFormat = "yyyy-MM-dd HH:mm:ss"

        // 获取日期结果

        let dateStr = df.stringFromDate(date)

        

        // 2. 执行 SQL

        // 提示:开发调试 删除 SQL 的时候,一定先写 `SELECT *`,确认无误之后,再替换成 `DELETE`

 

        SQLiteManager.sharedManager.queue.inDatabase { (db) -> Void in

            if db.executeUpdate(sql, dateStr) {

                print("删除了 \(db.changes()) 条缓存数据")

            }

        }

    }

 eg: DAL实例:

 

// 专门负责处理本地SQLite和网络数据

 

#import "HourseInfoDAL.h"

#import "DataDefine.h"

#import "SQLiteManger.h"

#import "ImageURLsDAO.h"

 

@class HouseListInfo;

@interface HourseInfoDAL ()

 

-(void)saveCacheData:(HouseListInfo *)hourseInfo;

 

@property (nonatomic, assign) int oldArrayCount;

@property (nonatomic, assign) int newArrayCount;

 

 

@end

 

@implementation HourseInfoDAL

 

#pragma mark 加载数据

-(void)loadHourseInfo:(HouseListInfo *)hourseInfo{

    

//    1> 检查本地是否缓存数据

//    2>  如果有返回数据

//    3> 如果没有,加载网络数据

    [self saveCacheData:hourseInfo];

//    4> 将网络返回的数据,保存在本地,一边后续使用

//    5> 返回网络数据

    

    

    

}

 

#pragma mark  保存房子数据

-(void)saveCacheData:(HouseListInfo *)hourseInfo{

    // 房子信息

    NSString* houseid = hourseInfo.houseid; // 房子ID

    NSString* listingCategory = hourseInfo.listingCategory;

    NSString* commission = hourseInfo.commission;

    NSString* bathrooms = hourseInfo.bathrooms;

    NSString* bedrooms = hourseInfo.bedrooms;

    NSString* listingStatus = hourseInfo.listingCategory;

    NSString* price = hourseInfo.price;

    NSString* propertySubType = hourseInfo.propertySubType;

    NSString* vadate = hourseInfo.vadate;

    NSString* imageURL = hourseInfo.imageURL;

    NSString* address = hourseInfo.address;

    NSString* moneytype = hourseInfo.moneytype;

    NSString* islike = hourseInfo.islike;

    NSString* imageSource = hourseInfo.imageSource;

 

    NSMutableDictionary * dict = [[NSMutableDictionary alloc] init];

    // 房子信息添加到字典中

    [dict setObject:houseid forKey:@"houseid"];

    [dict setObject:listingCategory forKey:@"listingCategory"];

    [dict setObject:commission forKey:@"commission"];

    [dict setObject:bathrooms forKey:@"bathrooms"];

    [dict setObject:bedrooms forKey:@"bedrooms"];

    [dict setObject:listingStatus forKey:@"listingStatus"];

    [dict setObject:price forKey:@"price"];

    [dict setObject:propertySubType forKey:@"propertySubType"];

    [dict setObject:vadate forKey:@"vadate"];

    [dict setObject:imageURL forKey:@"imageURL"];

    [dict setObject:address forKey:@"address"];

    [dict setObject:moneytype forKey:@"moneytype"];

    [dict setObject:islike forKey:@"islike"];

    [dict setObject:imageSource forKey:@"imageSource"];

    

    //是否登陆

    if (!g_has_login){

        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:@"\r\n请先登录" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"立即登录", nil];

        alert.tag = 101;

        [alert show];

        return;

    }

    

    NSLog(@"房子信息:%@",dict);

    

    //序列化 --- 房子数据

    NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:nil error:nil];

//    NSLog(@"json: %@",json);

    //SQL

        NSString  *sql = @"INSERT OR REPLACE INTO T_Showroom (houseId, hourseInfo, userId) VALUES (?, ?, ?);";

    

    SQLiteManger *manger = [SQLiteManger shareSQLiteManger];

    [manger.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        

        if ([db executeUpdate:sql, houseid, json, @"123"]) {

            NSLog(@"插入成功");

            

            rollback:false;

            return;

        }

    }];

    

    // 获取房子ID 已获得

    

    // 注册通知

    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tongzhi:) name:@"userId" object:nil];

    NSLog(@"哈哈哈woad ");

}

 

- (void)tongzhi:(NSNotification *)text{

//    NSLog(@"%@",text.userInfo[@"textOne"]);

    NSLog(@"-----接收到通知------");

    

}

 

//

#pragma mark  保存房子详情的相关数据

-(void)savaDetailCacheData:(NSDictionary *)dict{

    

    // 判断是否登录

    if (!g_has_login){

        UIAlertView* alert = [[UIAlertView alloc] initWithTitle:nil message:@"\r\n请先登录" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"立即登录", nil];

        alert.tag = 101;

        [alert show];

        return;

    }

    

    //    NSLog(@"房子详情的相关数据:%@", dict);

    

    // sql

     NSString  *sql = @"INSERT OR REPLACE INTO T_HourseDetails (houseId, hourseDetailInfo, userId) VALUES (?, ?, ?);";

 

    // 房子ID

    NSDictionary *houseManage = dict[@"houseManage"];

    NSString *hourseid = houseManage[@"id"];

    

    //序列化 --- 房子详情数据

    NSData *json = [NSJSONSerialization dataWithJSONObject:dict options:nil error:nil];

    

//    NSLog(@"房子详情序列化前:%@", dict);

//    NSLog(@"房子详情序列化后:%@",json);

    

    

    NSDictionary * images = dict[@"imageURLs"];

    

    // 可变数组, 存放iamgeUrls

    NSMutableArray * imageUrlsArray = [[NSMutableArray alloc] init];

    

    for (NSDictionary * dict in images) {

        

        NSString * imageUrl = dict[@"imageUrl"];

        NSLog(@"%@",imageUrl);

        

        [imageUrlsArray addObject:imageUrl];

    }

    

#pragma mark --- 下载详情界面图片

    

    for (int i = 0; i < imageUrlsArray.count; i++) {

        

        NSURL* url = nil;

        NSString* urlstr = [imageUrlsArray objectAtIndex:i];

        DLOG(@"urlstr  >>>>>:  %@",urlstr);

        if ([urlstr length] > 4 && [[[urlstr substringToIndex:4] lowercaseString] isEqualToString:@"http"])

        {

            url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",@"",urlstr]];

            DLOG(@"url  -->> :%@",url);

        }

        else

        {

            url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",BASEIMAGEURL,urlstr]];

            DLOG(@"url  ==>> :%@",url);

        }

 

//        NSString * image = [NSString stringWithFormat:@"image%d",i];

        

                    UIImageView *image = [[UIImageView alloc] init];

        

//                    [image sd_setImageWithURL:url placeholderImage:[UIImage imageNamed:@"fangyuan_cell_yongjin_bg"]];

        

        [image sd_setImageWithURL:url];  

    }    

   // 用户ID

    SQLiteManger *manger = [SQLiteManger shareSQLiteManger];

    [manger.queue inTransaction:^(FMDatabase *db, BOOL *rollback) {

        

        if ([db executeUpdate:sql, hourseid, json, @"123"]) {

            NSLog(@"插入成功");

            

        rollback:false;

            return;

        }

    }];

    

}

 

#pragma mark 检查房子本地数据  --->返回已经收藏的数据

-(NSArray *)checkChacheData {

    //SQL

    NSString * sql = @"SELECT houseId, hourseInfo, userId FROM T_Showroom \n";

    

    sql = [sql stringByAppendingFormat:@"WHERE userId = 123 \n"];

    

 

 

    // 执行sql语句

    NSArray * array = [[SQLiteManger shareSQLiteManger] execRecordSet:sql];

    NSLog(@"%d",self.arrayCountChange);

    // 定义一个bool值比较, 收藏的房子是否变化, (数据的增删)

    self.newArrayCount = (int)array.count;

    

    NSLog(@"新值:%d",self.newArrayCount);

    NSLog(@"旧值:%d", self.oldArrayCount);

    

    if (self.newArrayCount != self.oldArrayCount) {

        self.arrayCountChange = 1;

        NSLog(@"不相等");

    }else{

    

        self.arrayCountChange = 0;

    }

    

    self.oldArrayCount = self.newArrayCount;

    

    NSLog(@"旧值:%d", self.oldArrayCount);

 

    //可变的数据, 存储数据

    NSMutableArray *arrayM = [[NSMutableArray alloc] init];

    

    // 便利

    for (NSDictionary *dict in array) {

        

        NSData *jsonData = dict[@"hourseInfo"];

        

        NSLog(@"反序列化前:%@", jsonData);

        

        // 反序列化 --> 一条完整数据字典

        NSDictionary * result = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:nil];

        NSLog(@"反序列化后:%@", result);

        

        [arrayM addObject:result];

    }

    

    // 返回结果 - 如果没有查询到数据,会返回一个空的数组

    return arrayM;

}

 

#pragma 检查房子详情本地数据 --->返回已经在本地存在的数据

-(NSArray *) checkHourseDetailChacheData{

    

    //SQL

    NSString * sql = @"SELECT houseId, hourseDetailInfo, userId FROM T_HourseDetails \n";

    

    sql = [sql stringByAppendingFormat:@"WHERE userId = 123 \n"];

    

    // 执行sql语句

    NSArray * array = [[SQLiteManger shareSQLiteManger] execRecordSet:sql];

    

    //可变的数据, 存储数据

    NSMutableArray *arrayM = [[NSMutableArray alloc] init];

    

    // 便利

    for (NSDictionary *dict in array) {

        

        NSData *jsonData = dict[@"hourseDetailInfo"];

        

        NSLog(@"反序列化前:%@", jsonData);

        

        // 反序列化 --> 一条完整微博数据字典

        NSDictionary *result = [NSJSONSerialization JSONObjectWithData:jsonData options:nil error:nil];

        NSLog(@"反序列化后:%@", result);

        

        [arrayM addObject:result];

        

    }

    

    // 返回结果 - 如果没有查询到数据,会返回一个空的数组

    return arrayM;

}

 

#pragma mark 满足一定条件时清楚缓存 ---> 程序进入后台时调用

-(void)clearDataCache{

    

    // SQL

    NSString *sql = @"DELETE FROM T_Status WHERE   ;";

    

    // 执行SQL

    SQLiteManger *manger = [SQLiteManger shareSQLiteManger];

    [manger.queue inDatabase:^(FMDatabase *db) {

        [db executeUpdate:sql];

    }];

 

}

 

#pragma mark 取消收藏时删除,对应的数据

-(void)deleteDataCache:(NSString *)hourseId{

 

    

    NSLog(@"hourseId:%@",hourseId );

    

    // SQL

    NSString *sql = @"DELETE FROM T_Showroom \n";

    

    sql = [sql stringByAppendingFormat:@"WHERE houseId = %@ \n", hourseId];

    

//    NSLog(@"%@",sql);

    

    // 执行SQL

    SQLiteManger *manger = [SQLiteManger shareSQLiteManger];

    [manger.queue inDatabase:^(FMDatabase *db) {

        [db executeUpdate:sql];

    }];

}

 

@end

 

IOS开发中关于数据的本地化存储

标签:

原文地址:http://www.cnblogs.com/LZ-lizhen/p/5058417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!