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

对于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

时间: 2024-08-01 20:38:23

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

iOS开发中几种常见的存储方式

1.archive 归档 数据的保存 1: let result = NSKeyedArchiver.archiveRootObject(contacts, toFile: path as String) 2: println("保存结果\(result)") .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, "Courier New", cou

iOS开发中存储数据的方法

最近被问到一些关于iOS开发中对于数据存储的处理方式,感觉数据存储这个也是经常用到的一个功能的,有必要自己去整理和记录一下的. iOS开发中一般是有四种存储数据的方式,分别是: 1.NSUserDefaults:用来保存用户自己设置的一些属性,用户再次打开程序,或者开机后,这些信息还是存在,NSUserDefaults可以存储的类型包括NSString,NSData,NSNumber,NSDictionary,NSArray.如果要存储其他的数据类型,则需要转化为前面的一些类型,NSUSerDe

IOS开发中数据持久化的几种方法--NSUserDefaults

IOS开发中数据持久化的几种方法--NSUserDefaults IOS 开发中,经常会遇到需要把一些数据保存在本地的情况,那么这个时候我们有以下几种可以选择的方案: 一.使用NSUserDefault是最简单直接的一个办法: 1)保存数据: 1 // 实例化一个NSUserDefaults单例对象 2 NSUserDefaults *user = [NSUserDefaults standardUserDefaults]; 3 // 把一个数组array保存在key为allContact的键值

学习IOS开发UI篇--数据存储

iOS应用数据存储的常用方式 1.lXML属性列表(plist)归档 2.lPreference(偏好设置) 3.lNSKeyedArchiver归档(NSCoding) 4.lSQLite3 5.lCore Data Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时会备份该目录.例如,游戏应用可将游戏存档保存在该目录 tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除.应用没有运行时,系统也可能会清除该目录下的文件.iTunes同步设备时

ios开发中的4种数据持久化方式【二、数据库 SQLite3、Core Data 的运用】

               在上文,我们介绍了ios开发中的其中2种数据持久化方式:属性列表.归档解档.本节将继续介绍另外2种iOS持久化数据的方法:数据库 SQLite3.Core Data 的运用: 在本节,将通过对4个文本框内容的创建.修改,退出后台,再重新回到后台,来认识这两种持久化数据的方式.效果图如下[图1]: [图1 GUI界面效果图] [本次开发环境: Xcode:7.2     iOS Simulator:iphone6S plus   By:啊左]     一.数据库SQL

iOS开发中视图控制器ViewControllers之间的数据传递

iOS开发中视图控制器ViewControllers之间的数据传递 这里我们用一个demo来说明ios是如何在视图控制器之间传递重要的参数的.本文先从手写UI来讨论,在下一篇文章中讨论在storyboard中传递数据. 首先新建一个空工程,并添加一个根视图控制器类,如下图所示: # 在函数didFinishLunchingWithOption中添加几行代码,完成后如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 - (BOOL)application:(UIApplication

iOS 开发中用户记住账户,密码

在iOS开发中经常会用到记住账户.密码,以此来提高用户的体验.下面就浅谈一下账户.密码的存储. 一.登录 记录已登录用户步骤,存入偏好设置中存储放入一个数组. 具体存储 1:存储用户到偏好设置中,其中用户是一个数组向服务器响应客户端后的一些操作(如果响应数据成功)其中用户和密码是一一对应的 1.1先从沙盒中偏好设置中读取对应的用户集合 读取用户名: NSMutableArray *AccArys = [NSMutableArray arrayWithArray:[[NSUserDefaults

IOS开发中的UITableView与UITableViewCell

UITableView用来以表格的形式显示数据.关于UITableView,我们应该注意: (1)UITableView用来显示表格的可见部分,UITableViewCell用来显示表格的一行. (2)UITableView并不负责存储表格中的数据,而是仅仅存储足够的数据使得可以画出当前可见部分. (3)UITableView从UITableViewDelegate协议获取配置信息,从UITableViewDataSource协议获得数据信息. (4)所有的UITableView实现时实际上只有

iOS开发中的内存分配与分区

iOS开发中的内存分配与分区 关于RAM&ROM RAM与ROM就是具体的存储空间,统称为存储器. RAM(random access memory):运行内存,CPU可以直接访问,读写速度非常快,但是不能掉电存储.它又分为: 动态DRAM,速度慢一点,需要定期的刷新(充电),我们常说的内存条就是指它,价格会稍低一点,手机中的运行内存也是指它. 静态SRAM,速度快,我们常说的一级缓存,二级缓存就是指它,当然价格高一点. ROM(read only memory):存储性内存,可以掉电存储,例如