ios学习笔记-数据持久化

时间:2024-01-17 23:02:32

沙盒

沙盒是一种数据安全策略,只允许自己的应用访问目录。可以使用NSHomeDirectory()获取。

ios沙盒下有三个子目录:

1.Documents目录:用于存储比较大的文件活着需要频发女更新的数据,需要持久化的数据。获取代码:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

2.Library目录: 该目录下有Preferences和Caches两个目录。前者用于存放应用程序的设置数据和状态信息,后者用于存储缓存文件。获取代码:

NSString *libraryPath = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) lastObject];

3.tmp目录:临时文件目录,随应用程序退出而清除,不能进行iTunes或iCloud备份。获取代码:

NSString *tempPath = NSTemporaryDirectory();

属性列表(plist文件)

属性列表是一种XML文件。NSArray和NSDictionary类提供了读写plist文件的方法。

  • +arrayWithContentsOfFile:。NSArray类的类方法用于读取plist文件。
  • +dictionaryWithContentsOfFile:。NSDictionary类的类方法用于读取plist文件。
  • - initWithContentsOfFile:。NSArray和NSDictionary类都拥有此构造器方法,也能读取plist文件。
  • - writeToFile:atomically:。用于写入plist文件。atomically参数为是否适用辅助文件,如果为true则先写入到辅助文件中,然后将辅助文件重命名为目标文件。如果为false,则直接写入目标文件。

示例代码(写入):  

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

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

NSArray *array = @[@"a",@"b",@"c",@"d"];

NSString *plistPath = [self applicationDocumentsDirectoryFile];

[array writeToFile:plistPath atomically:YES];

示例代码(读取):

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

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

NSArray *array = [NSArray arrayWithContentsOfFile:path];

NSLog(@"%@",array);

对象归档

归档是一种序列化方式。需要归档对象的类必须实现NSCoding协议,而且每个成员变量应该是基本数据类型或实现NSCoding协议的某个类的实例。

写入:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

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

NSDictionary *array = @{@"":@"a",@"":@"b"};

[NSKeyedArchiver archiveRootObject:array toFile:path];

读取:

NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];

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

NSDictionary *array = [NSKeyedUnarchiver unarchiveObjectWithFile:path];

NSLog(@"%@",array);

SQLite数据库

SQLite可移植性强、小而容易使用。在运行时与实用他的程序共用相同的进程空间,不是单独的两个进程。在SQLite中,支持的常见数据类型有以下几种:

  • INTEGER。整型
  • REAL。浮点型
  • TEXT。字符串类型,采用UTF-8,UTF-16字符编码
  • BLOB。二进制,能存放任何二进制数据。

在SQLite中没有布尔类型,可采用整数0和1代替。也没有日期和时间类型,它们存储在TEXT、REAL、INTEGER类型中。

打开数据库:

/**
* 获取沙盒路径
*
* @return 沙盒路径
*/
- (NSString *)dataFilePath { NSArray *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *document = [path objectAtIndex:]; return [document stringByAppendingPathComponent:@"sqlite"]; } /**
* 打开数据库,如果没有则创建
*/
- (void)openSqlite {
sqlite3 *database;
//参数一:数据库文件路径(char类型) 参数二:数据库指针变量
if (sqlite3_open([[self dataFilePath] UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"open database faid!");
NSLog(@"数据库创建失败");
}
else {
char *err;
//如果没有Note表则创建。PRIMARY KEY 主键
NSString *sql = @"CREATE TABLE IF NOT EXISTS Note (cdate TEXT PRIMARY KEY,content TEXT)";
//参数一:数据库指针变量 参数二:sql语句(char类型) 参数三:回调函数 参数四:回调函数所需参数
if (sqlite3_exec(database, [sql UTF8String], NULL, NULL, &err) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"建表失败");
} //数据库打开失败,SQL语句执行失败,以及执行成功都需要关闭数据库,释放资源
sqlite3_close(database);
}
}

条件查询:

/**
* 根据条件查询一条
*
* @param text 主键
*
* @return 查询结果
*/
- (NSDictionary *)findById:(NSString *)text {
sqlite3 *database;
NSString *path = [self dataFilePath];
if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"数据库打开失败");
}
else {
NSString *sql = @"SELECT cdate,content FROM Note where cdate = ?"; NSLog(@"打开数据库"); //语句对象,SQL语句通过它执行
sqlite3_stmt *statement; /*
预处理过程
sqlite3_prepare_v2函数是SQL预处理语句。将SQL编译成二进制代码,提高执行速度 参数一:数据库指针变量 参数二:sql语句 参数三:全部SQL字符串长度。 如果nByte小于0,则函数取出zSql中从开始到第一个0终止符的内容;如果nByte不是负的,那么它就是这个函数能从zSql中读取的字节数的最大值。如果nBytes非负,zSql在第一次遇见’/000/或’u000’的时候终止 参数四:statement指针 参数五:SQL语句没有执行的部分语句。 上面提到zSql在遇见终止符或者是达到设定的nByte之后结束,假如zSql还有剩余的内容,那么这些剩余的内容被存放到pZTail中,不包括终止符
*/
int result = sqlite3_prepare_v2(database, [sql UTF8String], -, &statement, NULL);
NSLog(@"___________ %d",result);
if (result == SQLITE_OK) {
NSLog(@"预处理");
/*
sqlite3_bind_text:用于绑定SQL语句的参数
参数一:statement指针
参数二:参数序号(从1开始)
参数三:SQL语句参数(char类型)
参数四:字符串长度
参数五:函数指针,当数据库操作完成后会调用该函数
*/
sqlite3_bind_text(statement, , [text UTF8String], -, NULL); //执行。如果返回值为SQLITE_ROW说明数据没有遍历完
if (sqlite3_step(statement) == SQLITE_ROW) { /*
读取字符串类型的字段,第二个参数为select语句的索引(从0开始),下面就是读取cdata。
读取字段函数与字段类型对应,读取字段函数如下:
sqlite3_column_blob()
sqlite3_column_double()
sqlite3_column_int()
sqlite3_column_int64()
sqlite3_column_text()
sqlite3_column_text16()
*/
char *bufData = (char *)sqlite3_column_text(statement, ); NSString *strData = [[NSString alloc] initWithUTF8String:bufData]; //读取content
char *bufContent = (char *)sqlite3_column_text(statement, );
NSString *strContent = [[NSString alloc] initWithUTF8String:bufContent]; NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:strData,@"data",strContent,@"content", nil]; return dict;
}
} //释放statement
sqlite3_finalize(statement);
sqlite3_close(database);
}
return nil;
}

查询全部:

/**
* 查询全部数据
*
* @return 数组
*/
- (NSMutableArray *)findAll {
sqlite3 *database;
NSMutableArray *array = [[NSMutableArray alloc] init];
NSString *path = [self dataFilePath];
if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"数据库打开失败");
}
else {
NSString *sql = @"SELECT cdate,content FROM Note"; sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [sql UTF8String], -, &statement, NULL) == SQLITE_OK) { while (sqlite3_step(statement) == SQLITE_ROW) {
char *bufData = (char *)sqlite3_column_text(statement, );
NSString *strData = [[NSString alloc] initWithUTF8String:bufData]; NSLog(@"strData = %@",strData); char *bufContent = (char *)sqlite3_column_text(statement, );
NSString *strContent = [[NSString alloc] initWithUTF8String:bufContent]; NSLog(@"strContent = %@",strContent); NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:strData,@"data",strContent,@"content", nil];
[array addObject:dict];
} } sqlite3_finalize(statement);
sqlite3_close(database);
}
return array;
}

添加数据:

/**
* 添加数据
*
* @param model 所要插入的数据
*/
- (void)insert:(NSDictionary *)model {
sqlite3 *database;
NSString *path = [self dataFilePath];
if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"数据库打开失败");
}
else {
NSString *sql = @"INSERT OR REPLACE INTO Note(cdate,content) VALUES(?,?)"; sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [sql UTF8String], -, &statement, NULL) == SQLITE_OK) { char *bufData = (char *)[[model objectForKey:@"date"] UTF8String];
NSString *strContent = [model objectForKey:@"content"];
char *bufContent = (char *)[strContent UTF8String]; sqlite3_bind_text(statement, , bufData, -, NULL);
sqlite3_bind_text(statement, , bufContent, -, NULL); if (sqlite3_step(statement) != SQLITE_DONE) {
NSAssert(NO, @"插入数据失败");
}
else {
NSLog(@"插入成功");
} } sqlite3_finalize(statement);
sqlite3_close(database);
}
}

修改数据:

/**
* 添加数据
*
* @param model 所要插入的数据
*/
- (void)insert:(NSDictionary *)model {
sqlite3 *database;
NSString *path = [self dataFilePath];
if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"数据库打开失败");
}
else {
NSString *sql = @"INSERT OR REPLACE INTO Note(cdate,content) VALUES(?,?)"; sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [sql UTF8String], -, &statement, NULL) == SQLITE_OK) { char *bufData = (char *)[[model objectForKey:@"date"] UTF8String];
NSString *strContent = [model objectForKey:@"content"];
char *bufContent = (char *)[strContent UTF8String]; sqlite3_bind_text(statement, , bufData, -, NULL);
sqlite3_bind_text(statement, , bufContent, -, NULL); if (sqlite3_step(statement) != SQLITE_DONE) {
NSAssert(NO, @"插入数据失败");
}
else {
NSLog(@"插入成功");
} } sqlite3_finalize(statement);
sqlite3_close(database);
}
}

删除数据:

/**
* 删除数据
*
* @param cdata 所要删除数据的主键
*/
- (void)remove:(NSString *)cdata {
sqlite3 *database;
NSString *path = [self dataFilePath]; if (sqlite3_open([path UTF8String], &database) != SQLITE_OK) {
sqlite3_close(database);
NSAssert(NO, @"数据库打开失败");
}
else {
NSString *sql = @"DELETE from Note where cdate =?"; sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, [sql UTF8String], -, &statement, NULL) == SQLITE_OK) { sqlite3_bind_text(statement, , [cdata UTF8String], -, NULL); int result = sqlite3_step(statement); if (result != SQLITE_DONE) {
NSAssert(NO, @"删除数据失败");
}
else {
NSLog(@"删除数据成功");
} } sqlite3_finalize(statement);
sqlite3_close(database);
}
}