关于数据存储概念:

数据结构:

  • 基本对象:NSDictionary、NSArray和NSSet这些对象。
  • 复杂对象:关系模型、对象图和属性列表多种结构等。

存储方式:

  • 内存:内存存储是临时的,运行时有效的,但效率高。
  • 闪存:闪存则是一种持久化存储,但产生I/O消耗,效率相对低。

归档:把内存数据转移到闪存中进行持久化的操作的过程。

常用的数据存储方案:

  • 属性列表:NSArray、NSDictionary、NSData、NSString、NSNumber、NSDate等

        基本数据类型都支持这个机制,NSUserDefaults 也属于属性列表存储,常用

        于存储配置信息。这个机制可以将这些对象直接序列化到 plist 文件中,多用

        于少量数据的存储,效率较高。

simple code:

    // NSUserDefaults 默认
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:@"skyming" forKey:@"username"];
[userDefaults setObject:[NSDate date] forKey:@"date"];
[userDefaults setObject:@[@"a1",@"a2"] forKey:@"array"];
[userDefaults setInteger: forKey:@"code"];
NSLog(@"userDefaults: %@",[userDefaults dictionaryRepresentation]); NSString *username = [userDefaults objectForKey:@"username"];
NSDate *date = [userDefaults objectForKey:@"date"];
NSArray *array = [userDefaults objectForKey:@"array"];
NSInteger code = [userDefaults integerForKey:@"code"]; NSLog(@"username: %@ date:%@ \n array: %@ code: %d", username, date, array, code);
[userDefaults synchronize];
// NSUserDefaults 自定义
NSUserDefaults *defaults = [[NSUserDefaults alloc] init];
[defaults setPersistentDomain:[NSDictionary dictionaryWithObject:@"Hello" forKey:@"World"] forName:@"com.Sensoro.DefaultsTest"];
[defaults synchronize]; // 数组
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:];
NSString *myFile = [docPath stringByAppendingPathComponent:@"my.list"];
//读取文件
NSArray *array = [[NSArray alloc] initWithContentsOfFile:myFile];
//操作完若修改了数据则,写入文件
[array writeToFile:myFile atomically:YES];
  • 对象归档: 自定义对象常用的存储机制,对象必须实现 NSCoding 协议,NSCopying协议可选

simple code

 #pragma mark -
#pragma NSCoding协议实现实现
- (void)encodeWithCoder:(NSCoder *)aCoder
{ //encoder
[aCoder encodeObject:self.username forKey:@"username"];
[aCoder encodeObject:self.password forKey:@"password"];
}
- (id)initWithCoder:(NSCoder *)aDecoder
{
//decoder
if (self = [super init]) {
self.username = [aDecoder decodeObjectForKey:@"username"];
self.password = [aDecoder decodeObjectForKey:@"password"];
}
return self;
} #pragma NSCopying协议实现
- (id)copyWithZone:(NSZone *)zone
{
DSObj *copy = [[[self class] allocWithZone:zone] init];
return copy;
} // 读取
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:];
NSString *myFile = [docPath stringByAppendingPathComponent:@"dsObj.list"]; //写入归档文件
NSMutableData *datawrite = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:datawrite];
[archiver encodeObject:test forKey:@"data"];
[archiver finishEncoding];
[datawrite writeToFile:myFile atomically:YES]; //读取归档文件
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:myFile];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
DSObj *testread = [unarchiver decodeObjectForKey:@"data"];
[unarchiver finishDecoding];
NSLog(@"DSObjRead: %@ %@",[testread username], [testread password]);

当属性多时总不能一个个的添加吧,个人偏向于使用基于运行时的一个方案:

需要归档的对象只需要继承即可。

链接: https://github.com/skyming/SSObjectBase

  • SQLite: 用于存储查询需求较多的数据  

iOS的SDK里预置了SQLite3的库,开发者可以自建SQLite数据库。SQLite每次写入数据

都会产生IO消耗,把数据归档到相应的文件。SQLite擅长处理的数据类型其实与NSUser-

Defaults差不多,也是基础类型的小数据,只是从组织形式上不同。开发者可以以关系型

数据 库的方式组织数据,使用SQL DML来管理数据。一般来说应用中的格式化的文本类

数据可以存放在数据库中,尤其是类似聊天记录、Timeline等这些具有条件查询和排序需

求的数据。每一个数据库的句柄都会在内存中都会被分配一段缓存,用于提高查询效率。

另一个方面,由于查询缓存,当产生大量句柄或数据量较大时,会出现缓存过大,造成

内存浪费。

simple code

//open database
- (void)openDataBase
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *docPath = [paths objectAtIndex:];
NSString *myFile = [docPath stringByAppendingPathComponent:@"data.db"]; if (sqlite3_open([myFile UTF8String], &database)==SQLITE_OK)
{
NSLog(@"open sqlite db ok.");
}
else
{
NSLog( @"can not open sqlite db " ); //close database
sqlite3_close(database);
}
} //create table
- (void)createTable
{
char *errorMsg;
const char *createSql="create table if not exists persons (id integer primary key autoincrement,name text)"; if (sqlite3_exec(database, createSql, NULL, NULL, &errorMsg)==SQLITE_OK)
{
NSLog(@"create ok.");
}
else
{
NSLog( @"can not create table" );
[self ErrorReport:[NSString stringWithFormat:@"%s",createSql]];
}
} //insert table
- (void)insertTable
{
char *errorMsg; const char *insertSql="insert into persons (name) values ('skyming')";
if (sqlite3_exec(database, insertSql, NULL, NULL, &errorMsg)==SQLITE_OK)
{
NSLog(@"insert ok.");
}
else
{
NSLog( @"can not insert it to table" );
[self ErrorReport:[NSString stringWithFormat:@"%s",insertSql]];
}
} //query table
- (void)queryTable
{
const char *selectSql="select id,name from persons";
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(database, selectSql, -, &statement, nil)==SQLITE_OK)
{
NSLog(@"select ok.");
while (sqlite3_step(statement)==SQLITE_ROW)//SQLITE_OK SQLITE_ROW
{
int _id=sqlite3_column_int(statement, );
NSString *name=[[NSString alloc] initWithCString:(char *)sqlite3_column_text(statement, ) encoding:NSUTF8StringEncoding];
NSLog(@"row>>id %i, name>> %@",_id,name);
} }
else
{
//error
[self ErrorReport:[NSString stringWithFormat:@"%s",selectSql]];
} sqlite3_finalize(statement);
} //delete table
- (void)deleteTable
{
char *errorMsg;
[self openDataBase]; const char *sql = "DELETE FROM persons where id=24";
if (sqlite3_exec(database, sql, NULL, NULL, &errorMsg)==SQLITE_OK)
{
NSLog(@"delete ok.");
}
else
{
NSLog( @"can not delete it" );
[self ErrorReport:[NSString stringWithFormat:@"%s",sql]];
} }
//error
- (void)ErrorReport: (NSString *)item
{
char *errorMsg; if (sqlite3_exec(database, [item cStringUsingEncoding:NSUTF8StringEncoding], NULL, NULL, &errorMsg)==SQLITE_OK)
{
NSLog(@"%@ ok.",item);
}
else
{
NSLog(@"error: %s",errorMsg);
sqlite3_free(errorMsg);
}
}

SQLite的使用起来要比NSUserDefaults复杂的多,因此建议开发者使用SQLite要

搭配一个操作控件使用,可以简化操作。gaosboy 开发的SQLight是一款对SQLit

e操作的封装,把相对复杂的SQLite命令封装成对象和方法,可以供大家参考。

链接地址:https://github.com/gaosboy/SQLight

Github 星比较多的方案:FMDB

链接地址:https://github.com/ccgus/fmdb

  • CoreData,用于规划应用中的对象

官方给出的定义是,一个支持持久化的,对象图和生命周期的自动化管理方案。严格

意义上说CoreData是一个管理方案,他的持久化可以通过 SQLite、XML或二进制

文件储存。如官方定义所说,CoreData的作用远远不止储存数据这么简单,它可以

把整个应用中的对象建模并进行自动化的 管理。

上图,官方文档中解释CoreData给出的对象图示例

正如上图所示,MyDocument是一个对象实例,有两个Collection:Employee和

Department,存放各自的对象列表。 MyDocument、Employee和Department

三个对象以及他们之间的关系都通过CoreData建模,并可以通过save方法进行持久

化。从归档文件还原模型时CoreData并不是一次性把整个模型中的所有数据都载入

内存,而是根据运行时状态,把被调用到的对象实例载入内存。框架会自动控制这个

过程,从而达到控制内存消耗,避免浪费。无论从设计原理还是使用方法上看,Core-

Data都比较复杂。因此,如果仅仅是考虑缓存数据这个需求,CoreData绝对不是一个

优选方案。 CoreData的使用场景在于:整个应用使用CoreData规划,把应用内的数

据通过CoreData建模,完全基于CoreData架构应用。苹果官方给出的一个示例代码,

结构相对简单,可以帮助大家入门CoreData。

链接地址:

http://developer.apple.com/library/ios/#samplecode/Locations/Introduction/Intro.html#//apple_ref/doc/uid/DTS40008406

  • 使用基本对象类型定制的个性化缓存方案

之前提到的NSUserDefaults和SQLite适合存储基础类型的小数据,而CoreData则不适合

存储单一的数据,那么对于类似图片这 种较大的数据要用什么方式储存呢?gaosboy 给出

的建议就是:自己实现一套存储方案。首先要明确,这个所谓的定制方案适用于互联网应用

中对远程数据的缓存,几个限制条件缺一不可。从需求出发分析缓存数据有哪些要求:按Key

查找,快速读取,写入不影响正常操作,不浪费内存,支持归档。这些都是基本需求,那么再

进一步或许还需 要固定缓存项数量,支持队列缓存,缓存过期等。从这些需求入手设计一个

缓存方案并不十分复杂,Kache是笔者根据开发应用的需求开发的一套缓存组件,通 过分析

Kache希望可以给大家一个思路。

如上图所示,Kache扮演的是一个典型缓存角色。应用加载远程数据生成应用数据

对象的同时,通过Kache把数据缓存起来,再次请求则直接通过Kache获取数据。

缓存对象可以是NSDictionary、NSArray、NSSet或NSData这些可直接归档的类型,

每个缓存对象对应一个Key。缓存对象 包括数据和过期时间,内存中存放在一个单例

字典中,闪存中每个对象存为一个文件。Key空间按照各种顺序存放缓存对象的Key集

合,Pool为固定大小的 数组,当数量达到上限,最早过期的一个Key将被删除,对应的

缓存对象也被清除。Queue也是固定大小的数组,以先进先出的规则管理Key的增删。

每一次有新的缓存对象存入,自动检测Key空间中过期的集合并清除。此外,控件提供

save和load方法支持持久化和重新载入。Kache最初设计为存放图片缓存,之后也曾用

于缓存文本数据,由于使用了过期和归档相结合的逻辑,可以保证大部分命中的缓存对象

都在内存中,从而获取了较高的效率。读者可以从Github上获取Kache源码了解更多。

以上介绍了几种iOS开发中经常会遇到的储存数据方法,从其存储原理、使用方式和适用

场景几方面进行进了简单的对比。事实上每一款应用都很难采用一种单一的方案完成整个

应用的数据储存任务,需要根据不同的数据类型,选择最合适的方案,以便整个应用获得

良好的运行时性能。

 
simpleCode代码
相关链接:
 
 
 
 
 
 
 

IOS开发-数据库总结的更多相关文章

  1. iOS开发数据库篇—SQLite简单介绍

    iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等. 说明:离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式 (1 ...

  2. iOS开发数据库篇—SQL

    iOS开发数据库篇—SQL 一.SQL语句 如果要在程序运行过程中操作数据库中的数据,那得先学会使用SQL语句 1.什么是SQL SQL(structured query language):结构化查 ...

  3. iOS开发数据库篇—SQL代码应用示例

    iOS开发数据库篇—SQL代码应用示例 一.使用代码的方式批量添加(导入)数据到数据库中 1.执行SQL语句在数据库中添加一条信息 插入一条数据的sql语句: 点击run执行语句之后,刷新数据 2.在 ...

  4. iOS开发数据库篇—SQLite的应用

    iOS开发数据库篇—SQLite的应用 一.简单说明 在iOS中使用SQLite3,首先要添加库文件libsqlite3.dylib和导入主头文件. 导入头文件,可以使用库中的函数(是纯C语言的) 二 ...

  5. IOS开发数据库篇—SQLite模糊查询

    IOS开发数据库篇—SQLite模糊查询 一.示例 说明:本文简单示例了SQLite的模糊查询 1.新建一个继承自NSObject的模型 该类中的代码: // // YYPerson.h // 03- ...

  6. iOS开发数据库篇—SQLite常用的函数

    iOS开发数据库篇—SQLite常用的函数 一.简单说明 1.打开数据库 int sqlite3_open( const char *filename,   // 数据库的文件路径 sqlite3 * ...

  7. iOS开发数据库篇—FMDB简单介绍

    iOS开发数据库篇—FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来 ...

  8. iOS开发数据库篇—FMDB数据库队列

    iOS开发数据库篇—FMDB数据库队列 一.代码示例 1.需要先导入FMDB框架和头文件,由于该框架依赖于libsqlite库,所以还应该导入该库. 2.代码如下: // // YYViewContr ...

  9. 【转】 iOS开发数据库篇—SQLite简单介绍

    开始学SQLite啦, 原文: http://www.cnblogs.com/wendingding/p/3868893.html iOS开发数据库篇—SQLite简单介绍 一.离线缓存 在项目开发中 ...

  10. iOS开发 数据库FMDB

    iOS开发  数据库FMDB 1.简介 需求作用: 如果需要保存大量的结构较为复杂的数据时候, 使用数据库, 例如交规考试项目 常用的数据库: (1)Microsoft SQL Server 2000 ...

随机推荐

  1. Maven项目POM.xml详解

    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/20 ...

  2. Numpy库解析

    python中的axis 其实问题理解axis有问题,df.mean其实是在每一行上取所有列的均值,而不是保留每一列的均值.也许简单的来记就是axis=0代表往跨行(down),而axis=1代表跨列 ...

  3. WPF InitializeComponent() 方法介绍

    namespace WindowsApplication1 { /// <summary> /// Interaction logic for Window1.xaml /// </ ...

  4. Action请求流程分析

    Strut2流程分析-----从请求到Action方法() 首先请求会调用strutsPrepareAndExcuteFliter----(这个就是我们在web.xml文件中所配置的那个拦截器吧,所有 ...

  5. URI 、URL 和 URN

    URI URI 是 Uniform Resource Identifier 的缩写. Uniform 统一不同类型的资源.比如 txt.mp3.jpeg 等不同的类型的资源都可以使用 URI 来标识 ...

  6. 使用 postMessage + iframe 实现跨域通信

    一.postMessage window.postMessage() 方法可以安全地实现跨源通信.通常,对于两个不同页面的脚本,只有当执行它们的页面位于具有相同的协议(通常为https),端口号(44 ...

  7. 剑指Offer——构建乘积数组

    题目描述: 给定一个数组A[0,1,...,n-1],请构建一个数组B[0,1,...,n-1],其中B中的元素B[i]=A[0]*A[1]*...*A[i-1]*A[i+1]*...*A[n-1]. ...

  8. python中读取json文件报错,TypeError:the Json object must be str, bytes or bytearray,not ‘TextIOWrapper’

    利用python中的json读取json文件时,因为错误使用了相应的方法导致报错:TypeError:the Json object must be str, bytes or bytearray,n ...

  9. 【云安全与同态加密_调研分析(4)】云计算安全领域主要研究成果——By Me

    下表列举了在云安全问题研究表现突出的ICT公司和研究机构以及其在云计算安全方面主要研究成果: ◆ICT公司和研究机构(云计算安全领域主要研究成果)◆ ◆机构名称◆ ◆机构类别◆ ◆主要研究成果◆ ◆备 ...

  10. finecms万能标签list列表使用方法

    我们在用finecms建站时经常会用到调用文章列表的功能,这时我们可以用万能标签list来实现,当然还可以调用其他一些数据,下面我们就来看看list函数的相关参数和使用方法 action 支持&quo ...