数据持久化-CoreData、SQLite、FMDB

1.CoreData


1.1 CoreData概述


1)Core data 是数据持久存储的最佳方式

2)Core Data 基于model-view-controller(mvc)模式下,为创建分解的cocoa应用程序提供了一个灵活和强大的数据模型框架。


3)Core Data可以是你以图形界面的方式快速的定义app的数据模型,同时在你的代码中容易获取到它。 Core Data提供了基础结构去处理常用的功能,例如:保存,恢复,撤销和重做,允许你在app中继续创建新的任务。在使用 Core Data的时候,你不用安装额外的数据库系统,因为 Core Data使用内置的sqlite数据库。(里面自动生成三个字段)


4)Core Data提供了一个通用的数据管理解决方案来处理那些所有需要数据模型的app,app使用 Core Data来管理数据对象时很多的益处


5)苹果的图形用户界面编译器-interface builder(IB),提供了对core data controller对象的预构建,从而来减少app的用户界面和它的数据模型之间的粘滞代码。在使用core data的时候你不需要考虑sql的语法问题,也不需要管理相关的逻辑树去追踪用户的行为,更不用建立新的永久机制。当你写你app的用户界面到它的core data模型的时候,它已经为你把所有的东西都做好了。


6)core data将你app的模型层放入到一组定义在内存中的数据对象。core data会追踪这些对象的改变,同时可以根据需要做相反的改变,例如用户执行撤销命令。当core data在对你app数据的改变进行保存的时候,core data会把这些数据归档,并永久性保存。它保存的数据在一些常规的文件,你可以在Finder中可以进行管理,用spotlight进行搜索,备份到cd,和email给朋友或者家人


7)在使用core data框架的时候,你可以创建一个管理对象的模型,该模型提供了对模型对象的抽象定义,这也就是我们所知道的entities,它可以在我们的程序中使用。


8)core data是一个实体-关系模型,该模型是使用Xcode的数据模型设计工具来定义的,对数据实体以及他们的关系提供了丰富的环境。

1.2 CoreData的构成及特点


1.2.1 数据最终的存储类型


sqlite数据库,XML,二进制,内存里,或自定义数据类型(Mac OS X 10.5Leopard及以后的版本中,开发者也可以通过继承NSPersistentStore类以创建自定义的存储格式)


1.2.2好处


能够合理管理内存,避免使用sql的麻烦,高效


1.2.3 构成

1)NSManagedobjectContext(被管理的数据上下文)

操作实际内容(操作持久层)

作用:插入数据,查询数据,删除数据


2)NSManagedobjectModel(被管理的数据模型)

数据库所有表格或数据结构,包含各实体的定义信息

作用:添加实体的属性,建立属性间的关系

操作方法:视图编辑器,或代码


3)NSPersistentStoreCoordinator(持久化存储助理)

相当于数据库的连接器

作用:设置数据存储的名字,位置,存储方式,和存储时机


4)NSManagedobject(被管理的数据记录)

相当于数据库中的表格记录


5)NSFetchRequest(获取数据的请求)

相当于查询语句


6)NSEntityDescription(实体结构)

相当于表格结构


7)后缀为.xcdatamodeld的包

里面是.xcdatamodel文件,用数据模型编辑器编辑

编译后为.momd或.mom文件


1.2.4 依赖关系



1.3 基于sqlite数据库时,Core Data的简单使用


sqlite的区别:只能取出整个实体记录,然后分解,之后才能得到实体的某个属性


1.3.1 构建流程


包括:创建数据上下文,创建数据模型,创建数据持久化存储助理

(1)若是新建的工程,选择空白应用程序,next


此时生成的工程文件AppDelegate中,会自动生成被管理的数据上下文等相关代码


(2)比如AppDelegate.h文件中,自动生成


@property (readonly,strong,nonatomic) NSManagedobjectContext *managedobjectContext;

@property (readonly,nonatomic) NSManagedobjectModel *managedobjectModel;

@property (readonly,nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;


- (void)saveContext;

  • (NSURL *)applicationDocumentsDirectory;


方法saveContext表示:保存数据到持久层(数据库

方法applicationDocumentsDirectory表示:应用程序沙箱下的Documents目录路径

(例如/var/mobile/Applications/5FG80A45-DFB5-4087-A1B1-41342A977E21/Documents/)


(3)比如AppDelegate.h文件中,自动生成


@synthesizemanagedobjectContext = __managedobjectContext;

@synthesizemanagedobjectModel = __managedobjectModel;

@synthesizepersistentStoreCoordinator = __persistentStoreCoordinator;


保存数据到持久层

- (void)applicationWillTerminate:(UIApplication *)application

{

[self saveContext];

}

- (void)saveContext

{

NSError *error = nil;

NSManagedobjectContext *managedobjectContext = self.managedobjectContext;

if(managedobjectContext != nil) {

if([managedobjectContext hasChanges] && ![managedobjectContext save:&error]) {

NSLog(@"Unresolved error %@,%@",error,[error userInfo]);

abort();

}

}

}

Documents目录路径

- (NSURL *)applicationDocumentsDirectory

{

return[[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];

}

被管理的数据上下文

初始化的后,必须设置持久化存储助理

- (NSManagedobjectContext *)managedobjectContext

{

if(__managedobjectContext != nil) {

return__managedobjectContext;

}

NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];

if(coordinator != nil) {

__managedobjectContext = [[NSManagedobjectContext alloc] init];

[__managedobjectContext setPersistentStoreCoordinator:coordinator];

}

return__managedobjectContext;

}

被管理的数据模型

初始化必须依赖.momd文件路径,而.momd文件由.xcdatamodeld文件编译而来


- (NSManagedobjectModel *)managedobjectModel

{

if(__managedobjectModel != nil) {

return__managedobjectModel;

}

NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"TestApp"withExtension:@"momd"];

__managedobjectModel = [[NSManagedobjectModel alloc] initWithContentsOfURL:modelURL];

return__managedobjectModel;

}


持久化存储助理

初始化必须依赖NSManagedobjectModel,之后要指定持久化存储的数据类型,认的是NSsqliteStoreType,即sqlite数据库;并指定存储路径为Documents目录下,以及数据库名称


- (NSPersistentStoreCoordinator *)persistentStoreCoordinator

{

if(__persistentStoreCoordinator != nil) {

return__persistentStoreCoordinator;

}

NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"TestApp.sqlite"];

NSError *error = nil;

__persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedobjectModel:[self managedobjectModel]];

if(![__persistentStoreCoordinator addPersistentStoreWithType:NSsqliteStoreType configuration:nil URL:storeURL options:nil error:&error]) {

NSLog(@"Unresolved error %@,[error userInfo]);

abort();

}

return__persistentStoreCoordinator;

}


如果不是新工程,也可以自己写入相关代码

(4)此外还生成了TestApp.xcdatamodeld文件

(5)还自动链接了CoreData.framework

(6)在预编译头.pch文件中,加入导入了CoreData.h头文件

#import

1.3.2 创建数据模型(数据模型编辑器操作)


(1)创建实体(数据库表)和实体间的关系


选中.xcodedatamodel对象

在左下脚点击Add Entity添加实体

选中新添加属性,对属性进行命名,并设置属性的数据类型Attribute Type

选中一个实体,在底部工具栏点击Add Relationship添加关系





(2)自动生成模型类


选择你要创建的数据对象

1.3.3 数据模版


为每个实体生成一个NSManagedobject子类

上面设置数据和获取数据时,使用的是Key-Value方式,更好的方法是通过生成强类型的NSManagedobject的子类,通过类的成员属性来访问和获取数据

(1)在数据编辑器视图中选中实体对象,

选则file菜单,点击new,点击file...,选择Core Data项,选择NSManagedobject subclass,生成该实体同名的类,

继承于NSManagedobject






其中,@dynamic告诉编译器不做处理,使编译通过,其getter和setter方法会在运行时动态创建,由Core Data框架为此类属性生成存取方法


1.3.4 插入数据

在AppDelegate.m的application:didFinishLaunchingWithOptions:方法里,调用自定义方法

insertCoreData插入数据,代码如下:


- (void)insertCoreData

{

NSManagedobjectContext *context = [self managedobjectContext];

NSManagedobject *contactInfo = [NSEntityDescription insertNewObjectForEntityForName:@"School"inManagedobjectContext:context];

[contactInfo setValue:@"name B"forKey:@"name"];

[contactInfo setValue:@"classID 1"forKey:@"classID"];

[contactInfo setValue:@"persons 20"forKey:@"pensons"];

NSManagedobject *contactDetailInfo = [NSEntityDescription insertNewObjectForEntityForName:@"ContactDetailInfo"inManagedobjectContext:context];

[contactDetailInfo setValue:@"age 22"forKey:@"age"];

[contactDetailInfo setValue:@"name B"forKey:@"name"];

[contactDetailInfo setValue:@"classID 1"forKey:@"classID"];

[contactDetailInfo setValue:contactInfo forKey:@"name"];

[contactInfo setValue:contactDetailInfo forKey:@"classID"];

NSError *error;

if(![context save:&error])

{

NSLog(@"不能保存:%@",[error localizedDescription]);

}

}


创建数据上下文,调用insertNewObjectForName方法,创建两个数据记录NSManagedobject,然后就可以对之前数据模型编辑视图中定义的属性进行赋值。此时的数据只在内存中被修改,最后调用数据上下文的save方法,保存到持久层


1.3.5 查询数据


调用了insertCoreData之后,可以调用自定的查询方法dataFetchRequest来查询插入的数据


- (void)dataFetchRequest

{

NSManagedobjectContext *context = [self managedobjectContext];

NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo"inManagedobjectContext:context];

[fetchRequest setEntity:entity];

NSError *error;

NSArray *fetchedobjects = [context executeFetchRequest:fetchRequest error:&error];

for(NSManagedobject *infoinfetchedobjects) {

NSLog(@"classID:%d",[info valueForKey:@"classID"]);

NSLog(@"persons:%d",[info valueForKey:@"persons"]);

NSLog(@"name:%@",[info valueForKey:@"name"]);

NSManagedobject *details = [info valueForKey:@"name"];

NSLog(@"age:%d",[details valueForKey:@"age"]);

NSLog(@"classID:%d",[details valueForKey:@"classID"]);

}

}


fetchRequest相当于SQL查询语句的包装类,需要用setEntity方法,来指定具体查询的实体结构(表结构)

通过NSEntityDescription的entityForName方法来,返回指向该具体实体结构的指针

然后调用executeFetchRequest:error:方法,来执行查询操作,如果操作成功,则返回对应的数据记录数组

其中,可以通过NSManagedobject数据记录对象里关联的属性查询一个数据记录对象里的属性


之前用Key-Value的代码就可以修改为:

#import"School.h"

#import"Student.h"


- (void)insertCoreData

{

NSManagedobjectContext *context = [self managedobjectContext];

ContactInfo *contactInfo = [NSEntityDescription insertNewObjectForEntityForName:@"School"inManagedobjectContext:context];

contactInfo.name =@"name B";

contactInfo.birthday =@"classID 0";

contactInfo.age =@"persons 20";

ContactDetailInfo *contactDetailInfo = [NSEntityDescription insertNewObjectForEntityForName:@"Student"inManagedobjectContext:context];

contactDetailInfo.address =@"age 22";

contactDetailInfo.name =@"name B";

contactDetailInfo.telephone =@"classID 1";

contactDetailInfo.info = contactInfo;

contactInfo.details = contactDetailInfo;

NSError *error;

if(![context save:&error])

{

NSLog(@"不能保存:%@",[error localizedDescription]);

}

}


- (void)dataFetchRequest

{

NSManagedobjectContext *context = [self managedobjectContext];

NSFetchRequest *fetchRequest = [[[NSFetchRequest alloc] init] autorelease];

NSEntityDescription *entity = [NSEntityDescription entityForName:@"ContactInfo"inManagedobjectContext:context];

[fetchRequest setEntity:entity];

NSError *error;

NSArray *fetchedobjects = [context executeFetchRequest:fetchRequest error:&error];

for(Student *infoinfetchedobjects) {

NSLog(@"name:%@",info.name);

NSLog(@"age:%d",info.age);

NSLog(@"classID:%@",classID);

School *details = info.details;

NSLog(@"persons:%d",details.persons);

NSLog(@"classID:%d",details.classID);

}

}


1.3.6 数据库相关


1)打印隐藏的sql语句:

在Edit Scheme中选择Run,之后进入Arguments标签添加参数:“-com.apple.CoreData.sqlDebug 1”

2)使用sqlite存储时,数据库结构

存储的sqlite数据库名称:大写“Z”加上实体名称大写,一个实体相当于一张表

具体的字段名称:大写“Z”加上实体属性名称大写

2.sqlite


mac os x中sqlite库,它是一个轻量级功能强大的关系数据引擎,也很容易嵌入到应用程序。可以在多个平台使用,sqlite是一个轻量级的嵌入式sql数据库编程。与core data框架不同的是,sqlite是使用程序式的,sql的主要的API来直接操作数据表

sqlite3一个非常灵活的数据库系统,没有数据库服务器的概念,这应该算是回归了比较传统的数据库设计。

早期我们的数据都是直接存放在文件系统,由于简单的文件系统存在数据冗余、不一致、读取操作繁琐(每个数据结构都可能要编写自己的读写程序)等,慢慢形成了数据库管理系统,一套完整的数据库理论。

目前较为流行的Oracle,sqlServer,MysqL数据库系统均是服务器-客户端的概念,数据库服务器负责所有的数据管理、权限管理等,客户端按照一定格式发出请求即可。

sql则是较为流行的结构化查询语言,为众多上层应用提供简单方便的数据库读写操作等。

但是可想而知,服务器端必定是需要对sql请求进行解析然后执行的,那么这些执行程序还得回归更底层的语言,比如C&C++的实现。


注意:

第1代语言 机器语言(指令系统)其指令为二进制代码(0、1),直接对应芯片上的运算了

第2代语言 汇编语言 用“助记符”代替二进制代码,如用ADDA,B表示两数相加。

第3代语言 高级语言(面向过程)例如:C、JAVA、C++。

第4代语言(非过程化语言)  例如:sql语言。

第5代语言(智能化语言)    例如:Prolog语言)

sqlite3功能上来说,这是一个数据库系统,其本质上是由一套用C语言实现的对数据库文件的读写接口。此类接口支持sql语言。所以,这不需要什么服务器,也没有数据库权限管理。在程序中可以随时调用API创建一个数据库文件,进行数据存储,非常灵活易用。


2.1 建立sqlite3.0数据库

在Firefox中打开sqlite3(如果没有,选择工具->附加组件,添加即可)新建sqlite3数据库,Contacts,

建立一个members表,字段 id,integer,主键,自增;name,varchar;email,varchar,null;birthday,datetime,null。

向表中添加一些数据:

2.2 sqlite使用代码


新建Empty Appliation,添加一个HomeViewController,和一个组件libsqlite3.dylib,来支持sqlite3的连接,关闭,增删改查等操作。

1.)HomeViewController.h代码

#import

#import "sqlite3.h"


@interface HomeViewController : UIViewController{


sqlite3 *db; //声明一个sqlite3数据库

}


- (Nsstring *)filePath;//数据库文件的路径。一般在沙箱的Documents里边操作


@end


2.)HomeViewController.m代码

#import "HomeViewController.h"



@interface HomeViewController ()


@end



@implementation HomeViewController


//该方法用于返回数据库在Documents文件夹中的全路径信息

- (Nsstring *)filePath{


NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);

Nsstring *documentsDir = [paths objectAtIndex:0];

return [documentsDir stringByAppendingPathComponent:@"Contacts.sqlite"];

}


//打开数据库方法

- (void)openDB{


if (sqlite3_open([[self filePath] UTF8String],&db) != sqlite_OK) {

sqlite3_close(db);

NSAssert(0,@"数据库打开失败。");

}

}


//插入数据方法

- (void)insertRecordIntoTableName:(Nsstring *)tableName

withField1:(Nsstring *)field1 field1Value:(Nsstring *)field1Value

andField2:(Nsstring *)field2 field2Value:(Nsstring *)field2Value

andField3:(Nsstring *)field3 field3Value:(Nsstring *)field3Value{

//方法2:变量的绑定方法

Nsstring *sql = [Nsstring stringWithFormat:@"INSERT INTO '%@' ('%@','%@','%@') VALUES (?,?,?)",tableName,field1,field2,field3];

sqlite3_stmt *statement;

if (sqlite3_prepare_v2(db,[sql UTF8String],-1,&statement,nil) == sqlite_OK) {

sqlite3_bind_text(statement,1,[field1Value UTF8String],NULL);

sqlite3_bind_text(statement,2,[field2Value UTF8String],3,[field3Value UTF8String],NULL);

}

if (sqlite3_step(statement) != sqlite_DONE) {

NSAssert(0,@"插入数据失败!");

sqlite3_finalize(statement);

}


}

//查询数据

- (void)getAllContacts{


Nsstring *sql = @"SELECT * FROM members";

sqlite3_stmt *statement;

if (sqlite3_prepare_v2(db,nil) == sqlite_OK) {

while (sqlite3_step(statement) == sqlite_ROW) {

char *name = (char *)sqlite3_column_text(statement,0);

Nsstring *nameStr = [[Nsstring alloc] initWithUTF8String:name];

char *email = (char *)sqlite3_column_text(statement,1);

Nsstring *emailStr = [[Nsstring alloc] initWithUTF8String:email];

char *birthday = (char *)sqlite3_column_text(statement,2);

Nsstring *birthdayStr = [[Nsstring alloc] initWithUTF8String:birthday];

Nsstring *info = [[Nsstring alloc] initWithFormat:@"%@ - %@ - %@",

nameStr,emailStr,birthdayStr];

NSLog(info);

[nameStr release];

[emailStr release];

[birthdayStr release];

[info release];

}

sqlite3_finalize(statement);

}

}


- (void)viewDidLoad

{

[self openDB];

[self insertRecordIntoTableName:@"members" withField1:@"name" field1Value:@"李1" andField2:@"email" field2Value:@"df@qq.com" andField3:@"birthday" field3Value:@"12-45-78"];

[self insertRecordIntoTableName:@"members" withField1:@"name" field1Value:@"李2" andField2:@"email" field2Value:@"df@qq.com" andField3:@"birthday" field3Value:@"12-45-78"];

[self insertRecordIntoTableName:@"members" withField1:@"name" field1Value:@"李3" andField2:@"email" field2Value:@"df@qq.com" andField3:@"birthday" field3Value:@"12-45-78"];

[self getAllContacts];

sqlite3_close(db);

[super viewDidLoad];

}


@end


插入数据后的效果


查询效果


2.3 小结:

数据查询sqlite3_exec()函数执行sql语句,在没有返回值的情况下(比如创建表格、插入记录、删除记录等操作中)很好用。

也会用到sqlite3_stat结构、sqlite3_prepare_v2()函数sqlte3_step()函数sqlite3_finalize()函数

查询分三个阶段:准备阶段:sqlite3_stat、sqlite3_prepare_v2()

执行阶段:sqlte3_step()

终止阶段:sqlite3_finalize()

3.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=[FMDatabasedatabaseWithPath:database_path];



1、当数据库文件不存在时,FMDB会自己创建一个

2、 如果你传入的参数是空串:@"" ,则FMDB会在临时文件目录下创建这个数据库数据库断开连接时,数据库文件删除

3、如果你传入的参数是 NULL,则它会建立一个在内存中的数据库数据库断开连接时,数据库文件删除


2) 打开数据库



[dbopen]


返回BOOL型。


3) 关闭数据库



[dbclose]




3.2 数据库增删改等操作:


除了查询操作,FMDB数据库操作都执行executeUpdate方法,这个方法返回BOOL型。


看一下例子:


1)创建表:



if([dbopen]){

Nsstring*sqlCreateTable=[NsstringstringWithFormat:@"CREATETABLEIFNOTEXISTS'%@'('%@'INTEGERPRIMARYKEYAUTOINCREMENT,'%@'TEXT,'%@'INTEGER,'%@'TEXT)",TABLENAME,ID,NAME,AGE,ADDRESS];

BOOLres=[dbexecuteUpdate:sqlCreateTable];


if(!res){


NSLog(@"errorwhencreatingdbtable");

}else{


NSLog(@"successtocreatingdbtable");

}


[dbclose];

}





2)添加数据:



if([dbopen]){

Nsstring*insertsql1=[NsstringstringWithFormat:

@"INSERTINTO'%@'('%@','%@','%@')VALUES('%@','%@')",TABLENAME,NAME,AGE,ADDRESS,@"张三",@"13",@"济南"];


BOOLres=[dbexecuteUpdate:insertsql1];

Nsstring*insertsql2=[NsstringstringWithFormat:

@"INSERTINTO'%@'('%@',@"李四",@"12",@"济南"];


BOOLres2=[dbexecuteUpdate:insertsql2];

if(!res){


NSLog(@"errorwheninsertdbtable");

}else{


NSLog(@"successtoinsertdbtable");

}


[dbclose];

}


3)修改数据:




if([dbopen]){

Nsstring*updatesql=[NsstringstringWithFormat:

@"UPDATE'%@'SET'%@'='%@'WHERE'%@'='%@'",AGE,@"15",@"13"];


BOOLres=[dbexecuteUpdate:updatesql];

if(!res){

NSLog(@"errorwhenupdatedbtable");

}else{

NSLog(@"successtoupdatedbtable");

}

[dbclose];

}

4)删除数据:



if([dbopen]){

Nsstring*deletesql=[NsstringstringWithFormat:

@"deletefrom%@where%@='%@'",

TABLENAME,@"张三"];

BOOLres=[dbexecuteUpdate:deletesql];

if(!res){

NSLog(@"errorwhendeletedbtable");

}else{

NSLog(@"successtodeletedbtable");

}

[dbclose];

}




5)数据库查询操作:

查询操作使用了executeQuery,并涉及到FMResultSet。



if([dbopen]){

Nsstring*sql=[NsstringstringWithFormat:

@"SELECT*FROM%@",TABLENAME];

FMResultSet*rs=[dbexecuteQuery:sql];

while([rsnext]){

intId=[rsintForColumn:ID];

Nsstring*name=[rsstringForColumn:NAME];

Nsstring*age=[rsstringForColumn:AGE];

Nsstring*address=[rsstringForColumn:ADDRESS];

NSLog(@"id=%d,name=%@,age=%@address=%@",Id,name,age,address);

}

[dbclose];

}



FMDB的FMResultSet提供了多个方法获取不同类型的数据:







3.3 数据库多线程操作:


如果应用中使用了多线程操作数据库,那么就需要使用FMDatabaseQueue来保证线程安全了。 应用中不可在多个线程中共同使用一个FMDatabase对象操作数据库,这样会引起数据库数据混乱。 为了多线程操作数据库安全,FMDB使用了FMDatabaseQueue,使用FMDatabaseQueue很简单,首先用一个数据库文件地址来初使化FMDatabaseQueue,然后就可以将一个闭包(block)传入inDatabase方法中。 在闭包中操作数据库,而不直接参与FMDatabase的管理。



FMDatabaseQueue*queue=[FMDatabaseQueuedatabaseQueueWithPath:database_path];

dispatch_queue_tq1=dispatch_queue_create("queue1",NULL);

dispatch_queue_tq2=dispatch_queue_create("queue2",NULL);

dispatch_async(q1,^{

for(inti=0;i<50;++i){

[queueinDatabase:^(FMDatabase*db2){

Nsstring*insertsql1=[NsstringstringWithFormat:

@"INSERTINTO'%@'('%@','%@')VALUES(?,?,?)",

TABLENAME,ADDRESS];

Nsstring*name=[NsstringstringWithFormat:@"jack%d",i];

Nsstring*age=[NsstringstringWithFormat:@"%d",10+i];

BOOLres=[db2executeUpdate:insertsql1,@"济南"];

if(!res){

NSLog(@"errortoinsterdata:%@",name);

}else{

NSLog(@"succtoinsterdata:%@",name);

}

}];

}

});

dispatch_async(q2,^{

for(inti=0;i<50;++i){

[queueinDatabase:^(FMDatabase*db2){

Nsstring*insertsql2=[NsstringstringWithFormat:

@"INSERTINTO'%@'('%@',?)",ADDRESS];

Nsstring*name=[NsstringstringWithFormat:@"lilei%d",10+i];

BOOLres=[db2executeUpdate:insertsql2,@"北京"];

if(!res){

NSLog(@"errortoinsterdata:%@",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 iOS3.0 and later才能使用CoreData。


  • 至于sqlite和FMDB的使用情况,这个看个人喜好了,个人觉得没什么标准。FMDB就是对sqlite的封装,使用起来有方便的接口,没那么麻烦而已。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


SQLite架构简单,又有Json计算能力,有时会承担Json文件/RESTful的计算功能,但SQLite不能直接解析Json文件/RESTful,需要用Java代码硬写,或借助第三方类库,最后再拼成insert语句插入数据表,代码非常繁琐,这里就不展示了。参考前面的代码可知,入库的过程比较麻烦,不能只用SQL,还要借助Java或命令行。SPL是现代的数据计算语言,属于简化的面向对象的语言风格,有对象的概念,可以用点号访问属性并进行多步骤计算,但没有继承重载这些内容,不算彻底的面向对象语言。...
使用Python操作内置数据库SQLite以及MySQL数据库。
破解微信数据库密码,用python导出微信聊天记录
(Unity)SQLite 是一个软件库,实现了自给自足的、无服务器的、零配置的、事务性的 SQL 数据库引擎。SQLite 是在世界上最广泛部署的 SQL 数据库引擎。SQLite 源代码不受版权限制。本教程将告诉您如何使用 SQLite 编程,并让你迅速上手。.................................
安卓开发,利用SQLite实现登陆注册功能
相比大多数数据库而言,具有等优势,广泛应用于、等领域。
有时候,一个项目只有一个数据库,比如只有SQLite,或者MySQL数据库,那么我们只需要使用一个固定的数据库即可。但是一个项目如果写好了,有多个用户使用,但是多个用户使用不同的数据库,这个时候,我们就需要把软件设计成可以连接多个数据库的模式,用什么数据库,就配置什么数据库即可。4.Users实体类,这个实体类要和数据库一样的,形成一一对应的关系。11.Sqlite数据库,需要在代码里面创建数据库,建立表,再建立数据。8.我们开启MySQL数据库,然后进行调试,看程序的结果。2.安装SqlSugar。
基于Android的背单词软件,功能强大完整。
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。说白了就是使用起来轻便简单,
Android的简单购物车案例
SQLite,是一款轻型的数据库,是遵守ACID的关系型数据库管理系统,它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的,而且已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源的世界著名数据库...
Qt设计较为美观好看的登录注册界面(包含SQLite数据库以及TCP通信的应用)
SQLite是用C语言开发的跨平台小型数据库,可嵌入其他开发语言,也可在单机执行。SPL是用Java开发的跨平台的数据计算语言,可嵌入Java,可在单机执行,可以数据计算服务的形式被远程调用。两者的代码都是解释执行的。...
新建库.openDATA_BASE;新建表createtableLIST_NAME(DATA);语法:NAME关键字...<用逗号分割>删除表droptableNAME;查看表.schema查看表信息新建数据insertintoLIST_NAMEvalues();语法:CLASS,PARAMETER...,CLASS是类别,PARAMETER是参数<用逗号分割新建的
importsqlite3classDemo01:def__init__(self):self.conn=sqlite3.connect("sql_demo_001.db")self.cursor1=self.conn.cursor()self.cursor1.execute("select*fromtable_001wherename=?andid=?",('ssss&#0
 在客户端配置文件<configuration>节点下,添加:<connectionStrings>      <add name="localdb" connectionString="Data Source=config/local.db;Version=3;UseUTF16Encoding=True;" providerName="System.Data.SQLite.SQLiteFactory"/&g
提到锁就不得不说到死锁的问题,而SQLite也可能出现死锁。下面举个例子:连接1:BEGIN(UNLOCKED)连接1:SELECT...(SHARED)连接1:INSERT...(RESERVED)连接2:BEGIN(UNLOCKED)连接2:SELECT...(SHARED)连接1:COMMIT(PENDING,尝试获取EXCLUSIVE锁,但还有SHARED锁未释放,返回SQLITE_BUSY)连接2:INSERT...
SQLite是一种嵌入式数据库,它的数据库就是一个文件。由于SQLite本身是C写的,而且体积很小,所以,经常被集成到各种应用程序中,甚至在iOS和Android的App中都可以集成。Python就内置了SQLite3,所以,在Python中使用SQLite,不需要安装任何东西,直接使用。在使用SQLite前,我们先要搞清楚几个概念:表
设计思想————首先要确定有几个页面、和每个页面的大致布局由于是入门,我也是学习了不是很长的时间,所以项目比较low。。。。第一个页面,也就是打开APP的首页面:今天这个博客,先实现添加功能!:首先对主界面进行布局:其中activity_main.xml的代码为<?xmlversion="1.0"encoding="