扩展学习: ios8之后支持上传静态库
分析ios中各个存取方式的区别 plist和偏好设置 一般存储比较简单的数据或者系统自带的简单类型
对象归档一般用于存储小批量的对象 因为存取都是一次性的 所以数据多的情况下会造成性能低下 时间复杂度高
数据库(SQLite) 优化了数据的存储 节约时间 降低时间复杂度 易进行增删改查等 ->C语言Api
数据结构:
数组: 存储oc对象
栈 : 先进先出
队列 : 先进先出
树 (二叉树) : 遍历方式
图:
数据的存储方式分为:
线式存储 (数组等) 优点 ;易取 插入数据效率比较低 牵扯大量的数据移动
链式存储(nsset 无序数组) 反之 查询时需要遍历 利用节点来存储
FMDB
FMDB框架其实只是一层很薄的封装,主要的类也就两个:FMDatabase和FMResultSet。在使用FMDB的时候还需要导入libSQLite3.0.dylib。
iOS中原生的SQLite API在使用上相当不友好,在使用时,非常不便。于是,就出现了一系列将SQLite API进行封装的库,例如FMDB、 PlausibleDatabase、SQLitepersistentobjects等, FMDB ( https://github.com/ccgus/ FMDB) 是一款简洁、易用的封装库,这一篇文章简单介绍下FMDB的使用。
在FMDB下载文件后,工程中必须导入如下文件,并使用 libSQLite3.dylib 依赖包。
FMDB同时兼容ARC和非ARC工程,会自动根据工程配置来调整相关的内存管理代码。
FMDB常用类:
FMDatabase : 一个单一的SQLite数据库,用于执行SQL语句。
FMResultSet :执行查询一个FMDatabase结果集,这个和android的Cursor类似。
FMDatabaseQueue :在多个线程来执行查询和更新时会使用这个类。
3.1 数据基本操作
1) 创建数据库:
db= [FMDatabase databaseWithPath:database_path];
1、当数据库文件不存在时,FMDB会自己创建一个。
2、 如果你传入的参数是空串:@"" ,则FMDB会在临时文件目录下创建这个数据库,数据库断开连接时,数据库文件被删除。
3、如果你传入的参数是 NULL,则它会建立一个在内存中的数据库,数据库断开连接时,数据库文件被删除。
2) 打开数据库:
返回BOOL型。
3) 关闭数据库:
[dbclose]
3.2 数据库增删改等操作:
除了查询操作,FMDB数据库操作都执行executeUpdate方法,这个方法返回BOOL型。
看一下例子:
1)创建表:
if ([db open]) {
NSString *sqlCreateTable = [NSString stringWithFormat:@"CREATE TABLE IF NOT EXISTS '%@' ('%@' INTEGER PRIMARY KEY AUTOINCREMENT, '%@' TEXT, '%@' INTEGER, '%@' TEXT)" ,TABLENAME,ID,NAME,AGE,ADDRESS];
BOOL res = [db executeUpdate:sqlCreateTable];
if (!res) {
NSLog(@ "error when creating db table" );
} else {
NSLog(@ "success to creating db table" );
}
[db close];
}
2)添加数据:
if ([db open]) {
NSString *insertSql1= [NSString stringWithFormat:
@"INSERT INTO '%@' ('%@', '%@', '%@') VALUES ('%@', '%@', '%@')", TABLENAME, NAME, AGE, ADDRESS, @ "张三" , @ "13" , @ "济南" ];
BOOL res = [db executeUpdate:insertSql1];
NSString *insertSql2 = [NSString stringWithFormat:
@"INSERT INTO '%@' ('%@', '%@', '%@') VALUES ('%@', '%@', '%@')",TABLENAME, NAME, AGE, ADDRESS, @ "李四" , @ "12" , @ "济南" ];
BOOL res2 = [db executeUpdate:insertSql2];
if (!res) {
NSLog(@"error when insert db table");
} else {
NSLog(@"success to insert db table");
}
[db close];
}
3)修改数据:
if ([db open]) {
NSString *updateSql = [NSString stringWithFormat:
@"UPDATE '%@' SET '%@' = '%@' WHERE '%@' = '%@'",TABLENAME, AGE, @ "15" ,AGE, @ "13" ];
BOOL res = [db executeUpdate:updateSql];
if (!res) {
NSLog(@"error when update db table");
} else {
NSLog(@"success to update db table");
}
[db close];
}
4)删除数据:
if ([db open]) {
NSString *deleteSql = [NSString stringWithFormat:
@ "delete from %@ where %@ = '%@'" ,
TABLENAME, NAME, @ "张三" ];
BOOL res = [db executeUpdate:deleteSql];
if (!res) {
NSLog(@"error when delete db table");
} else {
NSLog(@"success to delete db table");
}
[db close];
}
5)数据库查询操作:
查询操作使用了executeQuery,并涉及到 FMResultSet。
if ([db open]) {
NSString * sql = [NSString stringWithFormat:
@ "SELECT * FROM %@" ,TABLENAME];
FMResultSet * rs = [db executeQuery:sql];
while ([rs next]) {
int Id = [rs intForColumn:ID];
NSString * name = [rs stringForColumn:NAME];
NSString * age = [rs stringForColumn:AGE];
NSString * address = [rs stringForColumn:ADDRESS];
NSLog(@"id = %d, name = %@, age = %@ address = %@", Id, name, age, address);
}
[db close];
}
FMDB的FMResultSet提供了多个方法来获取不同类型的数据:
3.3 数据库多线程操作:
如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。
FMDatabaseQueue* queue = [FMDatabaseQueue databaseQueueWithPath:database_path];
dispatch_queue_t q1 = dispatch_queue_create( "queue1" , NULL);
dispatch_queue_t q2 = dispatch_queue_create( "queue2" , NULL);
dispatch_async(q1, ^{
for ( int i = 0; i < 50; ++i) {
[queue inDatabase:^(FMDatabase *db2) {
NSString *insertSql1= [NSString stringWithFormat:
@ "INSERT INTO '%@' ('%@', '%@', '%@') VALUES (?, ?, ?)" ,
TABLENAME, NAME, AGE, ADDRESS];
NSString * name = [NSString stringWithFormat:@ "jack %d" , i];
NSString * age = [NSString stringWithFormat:@ "%d" , 10+i];
BOOL res = [db2 executeUpdate:insertSql1, name, age,@ "济南" ];
if (!res) {
NSLog(@ "error to inster data: %@" , name);
} else {
NSLog(@ "succ to inster data: %@" , name);
}
}];
}
});
dispatch_async(q2, ^{
for ( int i = 0; i < 50; ++i) {
[queue inDatabase:^(FMDatabase *db2) {
NSString *insertSql2= [NSString stringWithFormat:
@ "INSERT INTO '%@' ('%@', '%@', '%@') VALUES (?, ?, ?)" ,
TABLENAME, NAME, AGE, ADDRESS];
NSString * name = [NSString stringWithFormat:@ "lilei %d" , i];
NSString * age = [NSString stringWithFormat:@ "%d" , 10+i];
BOOL res = [db2 executeUpdate:insertSql2, name, age,@ "北京" ];
if (!res) {
NSLog(@ "error to inster data: %@" , name);
} else {
NSLog(@ "succ to inster data: %@" , name);
}
}];
}
});
4.总结
- CoreData允许用户使用代表实体和实体间关系的高层对象来操作数据。它也可以管理串行化的数据,提供对象生存期管理与object_graph 管理,包括存储。Core Data直接与 SQLite 交互,避免开发者使用原本的 SQL 语句.
- 上面的三种,都是在什么情况下使用呢?大多数人肯定是根据自己使用某项技术的时间也就是掌握的熟练程度来决定,例如以前没用过CoreData,在编写ios程序的时候还是使用自己比较拿手的SQLite,或者可能会考虑到在使用coredata自己还要花费额外的时候去学习。
- 但是仔细想一想,CoreData是苹果自己弄的框架,它其实还是和SQLite进行交互的,只是在交互的时候或者处理数据的时候进行了很多的优化,CoreData可以缩小你的代码量,而且CoreData已经优化过很多个版本,还提供了出色的安全性和错误处理之外,还提供了对任何竞争性方案的最好的内存可扩展性。换句话说就是,你可能花费了很长时间为某个问题进行优化精心制作了一个方案,但是在性能上的优势和CoreData相比,还是相差深远的。
- 另外就是CoreData与Mac OS X的集成非常的好,CoreData也和IB进行了结合,允许你创建用户界面,这样可以帮助你缩短应用程序的设计,实施以及调试周期。
- 所以在编写程序的时候尽量使用CoreData,这样才是最优的选择。只有在Core Data is available on iOS 3.0 and later才能使用CoreData。
- 至于SQLite和FMDB的使用情况,这个看个人喜好了,个人觉得没什么标准。FMDB就是对SQLite的封装,使用起来有方便的接口,没那么麻烦而已。