数据缓存

缓存分为:内存缓存 和 数据持久化(磁盘缓存)

内存缓存:

内存缓存是指当前程序运行空间,内存缓存速度快容量小,它是供cpu直接读取,

比如我们打开一个程序,他是运行在内存中的,关闭程序后内存又会释放。

常用框架:NSCache, YYMemoryCache.

我们常说的分区(从高地址到低地址):栈区,堆区, 全局区, 常量区, 代码区。 就是内存的范畴。

所以内存缓存指的就是将数据存储到这些区域。 一般是将数据缓存到堆区。

频繁的从磁盘中读取数据是比较耗性能的。 所以一般是先从磁盘中取到数据,存到内存缓存中,以达到性能优化。

磁盘缓存

就是 数据持久化。 

就是将数据保存到硬盘中(沙盒中),使得在应用程序或机器重启后可以继续访问之前保存的数据。

沙盒的结构

沙盒的路径

NSHomeDirectory();

1、Documents

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

2、Library

2.1 Caches

NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES).firstObject;

2.2 Preference

这个文件夹里存的是 通过NSUserDefault 方式存储的plist文件

//获取Preferences目录. 通常情况下,Preferences有系统维护,所以我们很少去操作它。

NSString *preferPath = [LibraryPath stringByAppendingPathComponent:@"Preferences"];

3、tmp

NSString *path = NSTemporaryDirectory();

缓存存放路径的规定:

用户生成的文件放在documents,自己的文件放在library/cache里面。

如果你做个记事本的app,那么用户写了东西,总要把东西存起来。那么这个文件则是用户自行生成,就放在documents文件夹里面。

如果你有一个app,需要和服务器配合,经常从服务器下载东西,展示给用户看。那么这些下载下来的东西就放在library/cache。

使用**Xcode**获取沙盒文件**(**模拟器和真机**)** 查看沙盒内容

[https://blog.csdn.net/wangxiaopeng1103/article/details/52947521](https://blog.csdn.net/wangxiaopeng1103/article/details/52947521)

数据持久化存储的几种方式:

[https://blog.csdn.net/jiankeufo/article/details/79347330](https://blog.csdn.net/jiankeufo/article/details/79347330)

**1.plist**文件

这个方法可以指定存储在沙盒的路径。

writeToFile方法。 

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

NSString *fileName = [path stringByAppendingPathComponent:@"123.plist"];

NSArray *array = @[@"123", @"456", @"789"];

[array writeToFile:fileName atomically:YES];

NSArray *result = [NSArray arrayWithContentsOfFile:fileName];

NSLog(@"%@", result);

**2.**偏好设置**preference**

在沙盒的preference目录下的一个以此应用包名来命名的plist文件。

NSUserDefaults存储不可变类型数据

//1.获得NSUserDefaults

NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

//2.向文件中写入内容

[userDefaults setObject:@"AAA" forKey:@"a"];

[userDefaults setBool:YES forKey:@"sex"];

[userDefaults setInteger:21 forKey:@"age"];

//2.1立即同步

[userDefaults synchronize];

//3.读取文件

NSString *name = [userDefaults objectForKey:@"a"];

BOOL sex = [userDefaults boolForKey:@"sex"];

NSInteger age = [userDefaults integerForKey:@"age"];

NSLog(@"%@, %d, %ld", name, sex, age);

**3.**归档**NSKeyedArchiver** 解档**NSKeyedUnarchiver**

遵循NSCoding

存储的是 .data文件

//1.遵循NSCoding协议 

@interface Person : NSObject <NSCoding>

//2.设置属性

@property (strong, nonatomic) UIImage *avatar;

@property (copy, nonatomic) NSString *name;

@property (assign, nonatomic) NSInteger age;

@end

//实现协议的两个方法

//解档

- (id)initWithCoder:(NSCoder *)aDecoder {

if ([super init]) {

self.avatar = [aDecoder decodeObjectForKey:@"avatar"];

self.name = [aDecoder decodeObjectForKey:@"name"];

self.age = [aDecoder decodeIntegerForKey:@"age"];

}

return self;

}

//归档

- (void)encodeWithCoder:(NSCoder *)aCoder {

[aCoder encodeObject:self.avatar forKey:@"avatar"];

[aCoder encodeObject:self.name forKey:@"name"];

[aCoder encodeInteger:self.age forKey:@"age"];

}

使用:

NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];

Person *person = [[Person alloc] init];

person.avatar = self.avatarView.image;

person.name = self.nameField.text;

person.age = [self.ageField.text integerValue];

//写入person.data文件    

[NSKeyedArchiver archiveRootObject:person toFile:file];

NSString *file = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"person.data"];

//根据person.data文件读取数据    

Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:file];

if (person) {

self.avatarView.image = person.avatar;

self.nameField.text = person.name;

self.ageField.text = [NSString stringWithFormat:@"%ld", person.age];

}

FMDB

[https://www.cnblogs.com/Yun-Longcom/p/6008724.html](https://www.cnblogs.com/Yun-Longcom/p/6008724.html)

SQL语法

[https://blog.csdn.net/m0_37177053/article/details/78350202](https://blog.csdn.net/m0_37177053/article/details/78350202)

FMDatabase : 一个单一的SQLite数据库,用于执行SQL语句。

FMResultSet :执行查询一个FMDatabase结果集。

FMDatabaseQueue :在多个线程来执行查询和更新时会使用这个类

首先创建数据库:

NSString *path=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

path=[path stringByAppendingPathComponent:@"test.sqlite"];

FMDatabase *dataBase= [FMDatabase databaseWithPath:path]; //数据库有数据库的名称 test.sqlite

创建表:

NSString * create1=@"create table if not exists t_user(id integer autoincrement primary key,name varchar)"; 

**BOOL c1= [dataBase executeUpdate:create1]; //**表有表的名称 **t_user**

插入数据

**NSString * insertSql = @"insert into t_user(id,name) values(?,?)";**

bool inflag1 = [dataBase executeUpdate:insertSql,@(2),@"admin"];

if(inflag1){

NSLog(@“增加成功");

}

删除语句

**NSString * delete=@"delete from t_user";**

BOOL dflag= [dataBase executeUpdate:delete];

if(dflag){

NSLog(@"删除成功");

}

修改语句

**NSString *update=@" update t_user set name=? ";**

BOOL flag= [dataBase executeUpdate:update,@"zhangsan"];

if(flag){

NSLog(@"修改成功");

}

查询语句

**NSString * sql=@" select * from t_user ";**

**FMResultSet *result=[dataBase executeQuery:sql];**

while(result.next){

int ids=[result intForColumn:@"id"];

NSString * name=[result stringForColumn:@"name"];

int ids=[result intForColumnIndex:0];

NSString * name=[result stringForColumnIndex:1];

NSLog(@"%@,%d",name, ids);     

}

注意:

创建表,增,删,改 都使用executeUpdate方法

- (BOOL)executeUpdate:(NSString*)sql, ...

- (BOOL)executeUpdateWithFormat:(NSString*)format, ...

- (BOOL)executeUpdate:(NSString*)sql withArgumentsInArray:(NSArray *)arguments

只有查询使用executeQuery方法

- (FMResultSet *)executeQuery:(NSString*)sql, ...

- (FMResultSet *)executeQueryWithFormat:(NSString*)format, ...

- (FMResultSet *)executeQuery:(NSString *)sql withArgumentsInArray:(NSArray *)arguments

多线程的操作

如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 

应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 

为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue。

使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理

NSString *path=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

path=[path stringByAppendingPathComponent:@"test.sqlite"];

//创建一个test.sqlite数据库

FMDatabaseQueue *queue=[FMDatabaseQueue databaseQueueWithPath:path]; 

[queue inDatabase:^(FMDatabase *db) {

//创建一个t_book表。

NSString * create=@"create table if not exists t_book(id integer,name varchar)";

BOOL c1= [db executeUpdate:create];

if(c1){

NSLog(@"成功");

}

}];

[queue inDatabase:^(FMDatabase *db) {

NSString * insertSql=@"insert into t_book(id,name) values(?,?)";

//插入语句1

bool inflag=[db executeUpdate:insertSql,@(2),@"admin"];

if(inflag){

NSLog(@"插入成功");

}

}];

[queue inDatabase:^(FMDatabase *db) {

//查询语句1

FMResultSet *data = [db executeQuery:@" select * from t_book "];

while (data.next) {

int ids=[data intForColumn:@"id"];

NSString *name=[data stringForColumn:@"name"];

NSLog(@"%@",name);

NSLog(@"%i",ids);   

}

}];

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,797评论 8 265
  • 曾几何时,望见过门开时你对我的一笑 它深深影印在我的心上 就如当年初识,踩上扫帚对你的一笑 他俩是如此的相像 静处...
    卿少游阅读 1,605评论 0 0
  • 天有意,终成命。 许多年后再回忆起2013,依然会因其特殊而无法忘记。就像上半年奶奶去世已然昭示之后的事情一样。 ...
    思遥阅读 3,873评论 0 1
  • 第三章 浴血西京 梁、陈两方主帅各自回帐一个时辰后,排兵布阵均已妥当。随后陈业下令,鼓声号角大作,大军兵分四路开拔...
    1891阅读 3,978评论 2 3
  • 这里只上效果图,完整代码请移至 本人博客 .欢迎转载,注明出处,谢谢^
    xiesj88阅读 4,969评论 1 2