1.iOS中數(shù)據(jù)存儲方式
- plist(NSArray/NSDictionary)
- preference(NSUserDefaults)
- NSCoding(NSKeyedArchiver/NSkeyedUnarchiver)
- SQlite3
- Core Data
優(yōu)缺點(diǎn)分析
- plist(屬性列表)是一種XML格式的文件,如果對象是NSString谷誓、NSDictionary、NSArray韧献、NSData、NSNumber等類型嚷那,就可以使用
writeToFile:atomically:encoding:error:
方法直接將對象寫入屬性列表文件中瑞驱。但是對于自定義類無法使用逆趋,而且只能存儲非常簡單的數(shù)據(jù)闷袒。 - preference(偏好設(shè)置)一般用來保存用戶的賬號滑蚯、密碼、字體大小等,也同樣只能存儲一些簡單數(shù)據(jù)類型,無法存儲自定義對象
- 基于以上缺點(diǎn),出現(xiàn)了NSCoding技術(shù),NSCoding可以存儲任何對象倦零。只有遵守了
NSCoding
協(xié)議的對象躏仇,可以實(shí)現(xiàn)encodeWithCoder
歸檔對象糟描,initWithCoder
恢復(fù)對象。 - 以上三種存在致命缺陷,無法存儲大量數(shù)據(jù)域慷,也無法實(shí)現(xiàn)非常便捷的CRUD(增刪改查)。每次操作都要從文件中讀取數(shù)據(jù)到內(nèi)存中宙枷,然后增刪改查,再寫入文件,以舊文件覆蓋新文件恤左。大量IO操作,非常耗費(fèi)性能夜赵。
- SQLite是純C語言嵌入式關(guān)系型數(shù)據(jù)庫,內(nèi)存開銷小乡革、效率高寇僧,廣泛使用于移動客戶端。
- Core Data基于SQList沸版,是蘋果推出的基于OC版本的數(shù)據(jù)庫技術(shù)嘁傀,比較龐大,比較重量級视粮,包裝了很多層细办,所以效率不及SQLite3。
2.SQLite基本操作
1.準(zhǔn)備工作
背景:在storyboard上添加兩個textField和label馒铃,用來輸入商品數(shù)據(jù)的名稱和價格蟹腾,點(diǎn)擊添加按鈕后痕惋,將其插入數(shù)據(jù)庫。
- 導(dǎo)入框架libsqlite3.0.tbd
- 包含主頭文件#import<sqlite3.h>
- 使用sqlite前先要打開數(shù)據(jù)庫
// 創(chuàng)建數(shù)據(jù)庫文件名shop.sqlite
NSString *fileName = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:@"shop.sqlite"];
// 打開數(shù)據(jù)庫
int status = sqlite3_open(fileName.UTF8String, &_dataBase);
if (status == SQLITE_OK) {
NSLog(@"打開數(shù)據(jù)庫成功");
// SQL創(chuàng)表語句娃殖,id字段:主鍵,name:名稱,price:價格
const char *sql = "CREATE TABLE IF NOT EXISTS t_shop (id integer PRIMARY KEY,name text NOT NULL,price real);";
char *error = NULL;
// 執(zhí)行sql語句
sqlite3_exec(self.dataBase, sql, NULL, NULL, &error);
if (error) {
NSLog(@"創(chuàng)表失敗:%s",error);
}
}else{
NSLog(@"打開數(shù)據(jù)庫失敗");
}
代碼解析:sqlite3_open()
將根據(jù)文件路徑打開數(shù)據(jù)庫值戳,如果數(shù)據(jù)庫文件不存在,系統(tǒng)會自動創(chuàng)建文件自動初始化數(shù)據(jù)庫炉爆。如果返回值status
等于常量SQLITE_OK
堕虹,表示數(shù)據(jù)庫打開成功。第二個參數(shù)_dataBase
是該控制器sqlite3
類型的屬性芬首,是一個打開的數(shù)據(jù)庫實(shí)例赴捞。數(shù)據(jù)庫文件的路徑必須以C字符串(而非NSString)傳入。一般服務(wù)器開發(fā)中打開數(shù)據(jù)庫郁稍,都需要使用sqlite3_close
(_dataBase
)關(guān)閉數(shù)據(jù)庫赦政,但在移動開發(fā)中,可以不用耀怜。
2.插入數(shù)據(jù)
//sql語句
NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_shop(name,price) VALUES('%@',%f);",self.nameField.text,self.priceField.text.doubleValue];
//執(zhí)行sql恢着,nameField和priceField是兩個textField輸入控件
sqlite3_exec(self.dataBase, sql.UTF8String, NULL, NULL, NULL);
代碼分析:sqlite3_exec()
可以執(zhí)行任何sql語句,比如創(chuàng)表财破、更新掰派、插入、刪除操作等等左痢。但一般不用它執(zhí)行查詢語句靡羡,因?yàn)樗粫祷夭樵兊降臄?shù)據(jù)
3.查詢數(shù)據(jù)
const char *sql = "SELECT name,price FROM t_shop";
//stmt指針是用來去除查詢結(jié)果
sqlite3_stmt *stmt = NULL;
//準(zhǔn)備
int status = sqlite3_prepare_v2(self.dataBase, sql, -1, &stmt, NULL);
if (status == SQLITE_OK) {//SQL語句正確,準(zhǔn)備成功
while (sqlite3_step(stmt)==SQLITE_ROW) {//成功取出一條數(shù)據(jù)
const char *name = (const char *)sqlite3_column_text(stmt, 0);//取第一個字段
const char *price = (const char *)sqlite3_column_text(stmt, 1);//q取第二個字段
NSLog(@"%s,%s",name,price);
}
}
sqlite3_finalize(stmt);//銷毀sqlite3_stmt對象
代碼解析:sqlite3_step()
返回SQLITE_ROW
代表遍歷到一條新紀(jì)錄,sqlite3_column_*()
用于獲取每個字段對應(yīng)的值俊性,第2個參數(shù)是字段的索引略步,從0開始。
4.模糊查找
// searchText是需要查詢的關(guān)鍵字
NSString *sql = [NSString stringWithFormat:@"SELECT name,price FROM t_shop WHERE name LIKE '%%%@%%' OR price LIKE '%%%@%%' ;", searchText, searchText];
sqlite3_stmt *stmt = NULL;
int status = sqlite3_prepare_v2(self.db, sql.UTF8String, -1, &stmt, NULL);
if (status == SQLITE_OK) {
while (sqlite3_step(stmt) == SQLITE_ROW) {
const char *name = (const char *)sqlite3_column_text(stmt, 0);
const char *price = (const char *)sqlite3_column_text(stmt, 1);
NSLog(@"%s,%s",name,price);
}
}
sqlite3_finalize(stmt);
代碼分析:模糊查找與一般查找除了sql
語句不同磅废,其他都是一樣的纳像。唯一需要注意的是,在數(shù)據(jù)庫中%表示任意東西拯勉,%S%表示字符S右邊和左邊可以是任何東西竟趾,在OC
中%表示特殊意義,所以要寫兩個(%%)表示一個(%)宫峦。
5.sqlite函數(shù)總結(jié)
// 1.打開數(shù)據(jù)庫
int sqlite3_open(
const char *filename, // 數(shù)據(jù)庫的文件路徑
sqlite3 **ppDb // 數(shù)據(jù)庫實(shí)例
);
// 2.執(zhí)行任何SQL語句
int sqlite3_exec(
sqlite3 *, // 一個打開的數(shù)據(jù)庫實(shí)例
const char *sql, // 需要執(zhí)行的SQL語句
int (*callback)(void*,int,char**,char**), // SQL語句執(zhí)行完畢后的回調(diào)
void *, // 回調(diào)函數(shù)的第1個參數(shù)
char **errmsg // 錯誤信息
);
// 3.檢查SQL語句的合法性(查詢前的準(zhǔn)備)
int sqlite3_prepare_v2(
sqlite3 *db, // 數(shù)據(jù)庫實(shí)例
const char *zSql, // 需要檢查的SQL語句
int nByte, // SQL語句的最大字節(jié)長度
sqlite3_stmt **ppStmt, // sqlite3_stmt實(shí)例岔帽,用來獲得數(shù)據(jù)庫數(shù)據(jù)
const char **pzTail
);
// 4.查詢一行數(shù)據(jù)
int sqlite3_step(sqlite3_stmt*); // 如果查詢到一行數(shù)據(jù),就會返回SQLITE_ROW
// 5.利用stmt獲得某一字段的值(字段的下標(biāo)從0開始)
double sqlite3_column_double(sqlite3_stmt*, int iCol); // 浮點(diǎn)數(shù)據(jù)
int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型數(shù)據(jù)
sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 長整型數(shù)據(jù)
const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二進(jìn)制文本數(shù)據(jù)
const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); // 字符串?dāng)?shù)據(jù)
最后
第一篇博客导绷,有很多問題犀勒,還沒寫全,如果想到了再做補(bǔ)充吧。使用這些sqlite
原生的C語言API非常費(fèi)力贾费,以后有空介紹一下iOS
中最常使用的數(shù)據(jù)庫框架FMDB
吧
That's All