常用的持久化方式包括以下幾種:
1.NSUserDefaults (偏好設(shè)置)
2.plist存儲(chǔ)(屬性列表)
3.NSKeyedArchiver(歸檔序列化存儲(chǔ))
4.SQLite3(iOS的嵌入式關(guān)系數(shù)據(jù)庫(kù))
5.FMDB (對(duì)sqlite的封裝)
6.Core Data (蘋果提供的持久化工具)
一、NSUserDefaults (偏好設(shè)置)上篇介紹過就不再介紹
優(yōu)點(diǎn):快速效率高,簡(jiǎn)單易用
缺點(diǎn):只能存儲(chǔ)常用的類型
二、plist存儲(chǔ)(屬性列表)
優(yōu)點(diǎn):快速效率高
缺點(diǎn):不靈活,只能存儲(chǔ)常用的類型
可以使用plist存儲(chǔ)的類型如下:NSArray、NSMutableArray、NSDictionary、NSMutableDictionary、NSData、NSMutableData、NSString、NSMutableString、NSNumber、NSDate
//寫入文件
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [doc stringByAppendingPathComponent:@"myself.plist"];
NSDictionary *dict = @{@"name": @"hello"};
[dict writeToFile:path atomically:YES];
//讀取文件
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:path];
三、歸檔(NSCoding NSKeyedArchiver NSKeyedUnarchiver)
優(yōu)點(diǎn):可以實(shí)現(xiàn)把自定義的對(duì)象存放在文件中
缺點(diǎn):必須實(shí)現(xiàn)協(xié)議,浸入性強(qiáng)
需要保存的對(duì)象必須遵守NSCoding協(xié)議,并且實(shí)現(xiàn)該協(xié)議中- (void)encodeWithCoder:(NSCoder )aCoder和 - (id)initWithCoder:(NSCoder )aDecoder方法。
//寫入文件
//YXPerson.h文件如下:
@interface YXPerson : NSObject<NSCoding>
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
@end
//YXPerson.m文件如下:
#import "YYPerson.h"
@implementation YYPerson
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
-(id)initWithCoder:(NSCoder *)aDecoder{
if (self=[super init]) {
self.name=[aDecoder decodeObjectForKey:@"name"];
self.age=[aDecoder decodeIntegerForKey:@"age"];
}
return self;
}
@end
寫入和讀取:
//寫入對(duì)象
YXPerson *p=[[YXPerson alloc]init];
p.name=@"hello";
p.age=27;
NSString *docPath=[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)lastObject];
NSString *path=[docPath stringByAppendingPathComponent:@"person.hello"];
[NSKeyedArchiver archiveRootObject:p toFile:path];
//讀取對(duì)象
YXPerson *p=[NSKeyedUnarchiver unarchiveObjectWithFile:path];
四、SQLite3(iOS的嵌入式關(guān)系數(shù)據(jù)庫(kù))
優(yōu)點(diǎn):靈活、存儲(chǔ)大批量的數(shù)據(jù)
缺點(diǎn):使用復(fù)雜、性能需要自行優(yōu)化
- (void)openDB{
//獲取數(shù)據(jù)庫(kù)文件路徑
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *fileName = [doc stringByAppendingPathComponent:@"students.sqlite"];
//將OC字符串轉(zhuǎn)換為c語言的字符串
const char *cfileName = fileName.UTF8String;
//打開數(shù)據(jù)庫(kù)文件(如果數(shù)據(jù)庫(kù)文件不存在,那么該函數(shù)會(huì)自動(dòng)創(chuàng)建數(shù)據(jù)庫(kù)文件)
int result = sqlite3_open(cfileName, &_db);
if (result == SQLITE_OK) {//打開成功
NSLog(@"成功打開數(shù)據(jù)庫(kù)");
}else{
NSLog(@"打開數(shù)據(jù)庫(kù)失敗");
}
}
- (void)createTable{
//創(chuàng)建表
const char *sql = "CREATE TABLE IF NOT EXISTS t_student(id integer PRIMARY KEY AUTOINCREMENT,name text NOT NULL,age integer NOT NULL);";
char *errmsg= NULL;
int result = sqlite3_exec(_db, sql, NULL, NULL, &errmsg);
if (result==SQLITE_OK) {
NSLog(@"創(chuàng)建表成功");
}else{
NSLog(@"創(chuàng)建表失敗---%s",errmsg);
}
}
- (void)insertData{
//插入數(shù)據(jù)
for (int i=0; i<10; i++) {
//拼接sql語句
NSString *name = [NSString stringWithFormat:@"hello--%d",arc4random_uniform(100)];
int age = arc4random_uniform(20)+10;
NSString *sql = [NSString stringWithFormat:@"INSERT INTO t_student (name,age) VALUES ('%@',%d);",name,age];
//執(zhí)行SQL語句
char *errmsg = NULL;
sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errmsg);
if (errmsg) {//如果有錯(cuò)誤信息
NSLog(@"插入數(shù)據(jù)失敗--%s",errmsg);
}else{
NSLog(@"插入數(shù)據(jù)成功");
}
}
}
- (void)deleteData{
//刪除age小于15的數(shù)據(jù)
NSString *sql = [NSString stringWithFormat:@"DELETE FROM t_student WHERE age<15"];
char *errmsg = NULL;
sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errmsg);
if (errmsg) {
NSLog(@"刪除數(shù)據(jù)失敗");
}else{
NSLog(@"刪除數(shù)據(jù)成功");
}
}
- (void)updateData{
//大于20歲的都置為20歲
NSString *sql = [NSString stringWithFormat:@"UPDATE t_student set age=20 WHERE age>20"];
char *errmsg = NULL;
sqlite3_exec(_db, sql.UTF8String, NULL, NULL, &errmsg);
if (errmsg) {
NSLog(@"更新數(shù)據(jù)失敗");
}else{
NSLog(@"更新數(shù)據(jù)成功");
}
}
- (void)queryData{
const char *sql = "SELECT id,name,age FROM t_student WHERE age<20";
sqlite3_stmt *stmt = NULL;
//進(jìn)行查詢前的準(zhǔn)備工作
if(sqlite3_prepare_v2(_db, sql, -1, &stmt, NULL)==SQLITE_OK){//SQL語句沒有問題
NSLog(@"查詢語句沒有問題");
//每調(diào)用一次sqlite3_step函數(shù),stmt就會(huì)指向下一條記錄
while (sqlite3_step(stmt)==SQLITE_ROW) {//找到一條記錄
//取出數(shù)據(jù)
//(1)取出第0個(gè)字段的值(int)
int ID=sqlite3_column_int(stmt, 0);
//(2)取出第一列字段的值(text)
const unsigned char *name = sqlite3_column_text(stmt, 1);
//(3)取出第二列字段的值(int)
int age = sqlite3_column_int(stmt, 2);
printf("%d %s %d\n",ID,name,age);
}
}else{
NSLog(@"查詢語句有問題");
}
}
五、FMDB (對(duì)sqlite的封裝)
優(yōu)點(diǎn):是對(duì)sqlite的封裝,簡(jiǎn)單易用,接口比原生的SQLite接口簡(jiǎn)潔很多,提供一些多線程,緩存,線程池的功能
缺點(diǎn):因?yàn)樗荗C的語言封裝的,只能在iOS開發(fā)中使用
FMDB中重要的類
FMDatabase: 一個(gè)FMDatabase對(duì)象就代表一個(gè)單獨(dú)的SQLite數(shù)據(jù)庫(kù), 用來執(zhí)行SQL語句
FMResultSet: 使用FMDatabase執(zhí)行查詢后的結(jié)果集
FMDatabaseQueue: 用于在多線程中執(zhí)行多個(gè)查詢或更新, 它是線程安全的
**步驟: **
1.下載FMDB文件 , 將FMDB文件添加到工程中
2.導(dǎo)入libsqlite3.0.tbd框架,導(dǎo)入頭文件FMDatabase.h
3.代碼實(shí)現(xiàn),與SQLite使用步驟相似, 創(chuàng)建數(shù)據(jù)庫(kù)路徑,獲得數(shù)據(jù)庫(kù)路徑, 打開數(shù)據(jù)庫(kù),然后對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查,關(guān)閉數(shù)據(jù)庫(kù).
初始化數(shù)據(jù)庫(kù):
- (void)createDataBase {
// 獲取數(shù)據(jù)庫(kù)文件的路徑
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *path = [docPath stringByAppendingPathComponent:@"student.sqlite"];
NSLog(@"path = %@",path);
// 1..創(chuàng)建數(shù)據(jù)庫(kù)對(duì)象
FMDatabase *db = [FMDatabase databaseWithPath:path];
// 2.打開數(shù)據(jù)庫(kù)
if ([db open]) {
// do something
NSLog(@"Open database Success");
} else {
NSLog(@"fail to open database");
}
}
FMDB詳解,可參考:
iOS-FMDB詳解及使用
六、Core Data (蘋果提供的持久化工具)
Core Date是ios3.0后引入的數(shù)據(jù)持久化解決方案,它是是蘋果官方推薦使用的,不需要借助第三方框架。Core Date實(shí)際上是對(duì)SQLite的封裝,提供了更高級(jí)的持久化方式。在對(duì)數(shù)據(jù)庫(kù)操作時(shí),不需要使用sql語句,也就意味著即使不懂sql語句,也可以操作數(shù)據(jù)庫(kù)中的數(shù)據(jù)。
優(yōu)點(diǎn):相對(duì)于SQLite,更加簡(jiǎn)便
缺點(diǎn):對(duì)批量數(shù)據(jù)的處理執(zhí)行效率低
個(gè)人感覺Core Data使用體驗(yàn)不太好,雖然簡(jiǎn)化了sql語句,但是操作維護(hù)起來也很復(fù)雜。
有興趣可以參考:
iOS CoreData介紹和使用