GeekBand.iOS-数据持久化

2016/5/4 posted in  iOS学习笔记  

在我们日常的开发过程中,从网络下载的数据或者由用户产生的数据,一般都需要保存下来。并且可以供给用户进行进一步的修改。这个过程被称之为数据持久化。
在iOS中,我们可以采用如下技术进行数据的持久化:

  • 文件存储
  • SQLite嵌入式数据库
  • Core Data

文件存储

使用文件存储数据是最简单的方式,把数据以二进制的形式或字符串的形式写入文件。

沙盒

在iOS中,为了保证用户的数据安全。苹果对文件数据的访问采用了很大的限制。主要概述为Sandbox(沙盒)。即一个APP只能访问自己盒内的文件,对外部文件没有访问权限。

  • 根目录:NSHomeDictionary()
  • /Docouments:程序的文件数据保存在该目录下,iTunes备份时会包含该目录
  • /Library:储存程序的默认设置或其它状态信息
  • /Library/Caches:缓存文件。iTunes不备份,程序退出后不删除
  • /tmp:创建临时文件的地方,重启时会丢弃

APP Bundle

bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle,
cocoa提供了类NSBundle。
[NSBundle mainBundle]

NSFileManager

iOS的文件操作类,可以使用它来创建、删除文件。
常用操作请参考:NSFileManager

数据库SQLite

文件少说一些。在iOS中,我们同样可以使用数据库技术来自己创建各种表,来存储数据。在iOS中,我们使用嵌入式的SQLite作为数据库管理系统,创建用户数据。

什么是SQLite

SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。同样比起Mysql、PostgreSQL这两款开源的世界著名数据库管理系统来讲,它的处理速度比他们都快。目前我们使用SQLite 3.X版本。

使用SQLite

在iOS开发过程中,我们使用纯C语言的API来对其进行访问。主要步骤包括以下几点。

  1. 链接libSQLite3.dylib
  2. 使用SQLite3函数用于创建、打开数据库、执行SQL语句或关闭数据库

纯C语言API

//打开 SQLite
sqlite3* db = NULL
int result = sqlite3_open([path UTF8String],&db);

//执行SQL语句
int result = sqlite_exec(db,sql,NULL,NULL,&errorMsg);

//预定义SQL语句,可以有效防止SQL注入
sqlite3_stmt *stmt;
if(sqlite3_prepare_v2(db,sql,-1,&stmt,NULL)== SQLITE_OK){
    sqlite3_bind_text(stmt,1,"string",-1.NULL);
    sqlite3_bind_int(stmt,2,27);
}
sqlite3_finalize(stmt);


//结果集遍历
sqlite3_stmt *stmt;
if(sqlite3_prepare_v2(db,sql,-1,&stmt,NULL)== SQLITE_OK){
    while(sqlite3_step(stmt)==SQLITE_ROW){
        int _id = sqlite3_column_int(stmt,0);
        char* _name = sqlite3_column_text(stmt,1);
        NSString* name = [NSString stringWithUTF8String:_name];
        ...
    }
}
sqlite3_finalize(stmt);

//关闭SQLite
sqlite3_close(db);

FMDB

使用原生的API对SQLite访问效率挺高,但是在我们面向对象的开发过程中加入这样的代码,总是不太舒服。而且写起来也比较坑。于是伟大的第三方访问工具诞生啦。就是FMDB:https://github.com/ccgus/fmdb
使用方法如下:

//打开
FMDatabase *db = [FMDatabase databaseWithPath:(NSString *)path];
[db open];

//更新语句,executeUpdate这个方法后面必须是对象比如NSString,NSInteger,否则会崩溃
[db executeUpdate:@"insert into contacters(name,etc,telephone,email) values(?,?,?,?)",contacter.name,contacter.etc,contacter.telephone,contacter.email];
//取插入的id
contacter.contacterId = (int)[db lastInsertRowId];

//查询
FMResultSet* result = [db executeQuery:@"select * from contacters where id=?",contacterId];
while ([result next]) {
    contacter.contacterId = [result intForColumn:@"id"];
    contacter.name = [result stringForColumn:@"name"];
    contacter.telephone = [result stringForColumn:@"telephone"];
    contacter.email = [result stringForColumn:@"email"];
    contacter.etc = [result stringForColumn:@"etc"];
 }

//关闭
[db close];

CoreData简介

虽然使用了SQLite之后,可以实现所有的数据存储。但是,这并不是苹果最推荐的方法。官方最推荐的解决方案就是Core Data。

什么是CoreData

Apple提供的对象持久化框架,并不是数据库,但通常使用数据库作为底层存储。
基本概念

开始使用CoreData

  1. 在新建项目时勾选Use CoreData
  2. 在项目中*.xcdatamodel中构建模型

简单使用

//创建一个Entity对象
NSManagedObject* entity = [NSEntityDescription insertNewObjectForEntityForName:@"Entity" inManagedObjectContext:context];

//填充属性
[entity setValue:value forKey:@"key"];

//保存
NSError* error = nil;
[context save:&error];

//查询
NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"Entity"];

//排序过滤
request.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"key" ascending:YES]];
request.predicate = [NSPredicate predicateWithFormat:@"name like %@",@"j"];


//执行
NSError* error = nil;
NSArray* objs =[context executeFetchRequest:request error:&error];

//遍历,正常遍历数组即可。
for(NSManagedObject *obj in objs){
    NSLog(@"%@",[obj valueForKey:@"key"]);
}

//删除
[context deleteObject:managedObject];

参考资料

本部分只简要介绍CoreData。大坑慢慢填。送一些参考资料。
CoreData入门
CoreData入门知识