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, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
方法saveContext表示:儲存資料到持久層(資料庫)
方法applicationDocumentsDirectory表示:應用程式沙箱下的Documents目錄路徑
(例如/var/mobile/Applications/5FG80A45-DFB5-4087-A1B1-41342A977E21/Documents/)
(3)比如AppDelegate.h檔案中,自動生成
@synthesize managedObjectContext = __managedObjectContext;
@synthesize managedObjectModel = __managedObjectModel;
@synthesize persistentStoreCoordinator = __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, [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
- 生成對應的.h檔案
- 生成對應的l.m檔案
其中,@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 *info in fetchedObjects) {
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 *info in fetchedObjects) {
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代語言 彙編語言 用“助記符”代替二進制代碼,如用ADD A,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], -1,NULL);
SQLite3_bind_text(statement, 2, [field2Value UTF8String], -1,NULL);
SQLite3_bind_text(statement, 3, [field3Value UTF8String], -1,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, [sql UTF8String], -1, &statement, 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:@"[email protected]" andField3:@"birthday" field3Value:@"12-45-78"];
[self insertRecordIntoTableName:@"members" withField1:@"name" field1Value:@"李2" andField2:@"email" field2Value:@"[email protected]" andField3:@"birthday" field3Value:@"12-45-78"];
[self insertRecordIntoTableName:@"members" withField1:@"name" field1Value:@"李3" andField2:@"email" field2Value:@"[email protected]" 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 = [FMDatabase databaseWithPath:database_path];
1、當資料庫檔案不存在時,FMDB會自己建立一個。
2、 如果你傳入的參數是空串:@"" ,則FMDB會在臨時檔案目錄下建立這個資料庫,資料庫斷開連接配接時,資料庫檔案被删除。
3、如果你傳入的參數是 NULL,則它會建立一個在記憶體中的資料庫,資料庫斷開連接配接時,資料庫檔案被删除。
2) 打開資料庫:
[db open]
傳回BOOL型。
3) 關閉資料庫:
[db close]
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的封裝,使用起來有友善的接口,沒那麼麻煩而已。