歸檔和解檔

一、歸檔介紹

1.歸檔是指用某種格式來保存一個或多個對象,以便以后還原這些對象的過程。歸檔是將數(shù)據(jù)持久化的一種方式(所謂數(shù)據(jù)持久化,就是指在IOS開發(fā)過程中,將數(shù)據(jù)保存到本地,能夠讓程序的運行更加流暢)。

2.想要歸檔的數(shù)據(jù)對象,需要遵守NSCoding協(xié)議,并且該對象對應(yīng)的類必須提供encodeWithCoder:initWithCoder:方法。

3.歸檔就是將臨時數(shù)據(jù)保存成本地文件。

4.歸檔的缺點:歸檔的形式來保存數(shù)據(jù),只能一次性歸檔保存以及一次性解壓。所以只能針對小量數(shù)據(jù),而且對數(shù)據(jù)操作比較笨拙,即如果想改動數(shù)據(jù)的某一小部分,還是需要解壓整個數(shù)據(jù)或者歸檔整個數(shù)據(jù)。

二、XML歸檔

1.局限:數(shù)據(jù)類型只支持 NSString、NSDictionary、NSArayy、NSData、NSNumber(如果你想的話,可以將基本數(shù)據(jù)類型轉(zhuǎn)換為NSNumber再進行歸檔)。

2.比較方便,設(shè)置好歸檔路徑,一句話歸檔,一句話解檔。

3.歸檔文件格式:一般保存.plist文件。

/**** NSString和NSMutableString XML歸解檔 ****/NSString*str =@"hello world";

NSString*path = [[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]stringByAppendingPathComponent:@"hello.txt"];//atomically:這個參數(shù)意思是如果為YES,則保證文件的寫入原子性。就是說會先創(chuàng)建一個臨時文件,直到文件內(nèi)容寫入成功再導(dǎo)入到目標(biāo)文件里.如果為NO,則直接寫入目標(biāo)文件里.[str writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];//這里會覆蓋原來的內(nèi)容[@"hello world 2"writeToFile:path atomically:YES encoding:NSUTF8StringEncoding error:nil];

NSString*str2 = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];

/**** NSData和NSMutableData XML歸解檔 ****///任何對象都可以轉(zhuǎn)化為NSDataNSData *data = [@"hello world"dataUsingEncoding:NSUTF8StringEncoding];

NSString*path2 = [[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]stringByAppendingPathComponent:@"data.txt"];//歸檔[data writeToFile:path2 atomically:YES];//解檔[NSData dataWithContentsOfFile:path2];

/**** NSArray及NSMutableArray XML歸解檔 ****/

NSArray*array = @[@"test",@"test2"];

NSString *path3 = [[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]stringByAppendingPathComponent:@"array.plist"];//歸檔[array writeToFile:path3 atomically:YES];// 解檔NSArray *array = [NSArray arrayWithContentsOfFile:path3];

/**** NSArray XML歸解檔 ****/NSDictionary*dic = [NSDictionary dictionaryWithObjectsAndKeys:@"one",@"1",@"two",@"2", nil];

NSString*path4 = [[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]stringByAppendingPathComponent:@"dic.plist"];//歸檔[dic writeToFile:path4 atomically:YES];//解檔NSDictionary *ddic = [NSDictionary dictionaryWithContentsOfFile:path3];

三、NSKeyedArchiver歸檔

1.將各種類型的對象存儲到文件中,而且不僅僅是字符串、數(shù)組和字典類型,有一種更靈括的方法。就是利用NSKeyedArchiver類創(chuàng)建帶鍵(keyed)的檔案來完成。實現(xiàn)對我們自定義的類進行歸檔。

2.序列化與反序列化:將一個Objective-C對象轉(zhuǎn)換成NSData的操作叫做對象的序列化;而將一個NSData轉(zhuǎn)換成Objective-C對象的操作叫做對象的反序列化。一個Objective-C對象需要通過實現(xiàn)NSCoding協(xié)議以便支持序列化與反序列化

3.模擬場景:有一個學(xué)生類,學(xué)生擁有三個屬性name、age、book(一本書),其中book對應(yīng)Book類,Book類中擁有一個屬性bookName,歸檔一個數(shù)組,數(shù)組中有兩個student對象。

Student類

#import

#import"Book.h"@interfaceStudent : NSObject@property (nonatomic,copy)NSString*name;

@property (nonatomic,assign)intage;//除Student類之外,這里有一個自定義類型Book,所以Book類也需要實現(xiàn)NSCoding協(xié)議,從而進行歸檔@property (nonatomic,strong)Book *book;@end#import"Student.h"@implementationStudent-(void)encodeWithCoder:(NSCoder *)aCoder

{//歸檔姓名(NSString 對象)[aCoder encodeObject:self.name forKey:@"name"];//歸檔年齡(基本數(shù)據(jù)類型,如果是其它基本數(shù)據(jù)類型調(diào)用相應(yīng)的encode方法)[aCoder encodeInt:self.age forKey:@"age"];//歸檔自定義類(Book)[aCoder encodeObject:self.book forKey:@"book"];

}-(instancetype)initWithCoder:(NSCoder *)aDecoder

{if(self =[super init])

{//歸檔的key 寫的什么 對應(yīng)屬性解檔key就寫什么self.name = [aDecoder decodeObjectForKey:@"name"];

self.age= [aDecoder decodeInt32ForKey:@"age"];

self.book= [aDecoder decodeObjectForKey:@"book"];

}returnself;

}@end

同樣的,Book類也要實現(xiàn)

協(xié)議并重寫相應(yīng)的兩個方法。

NSKeyedArchiver歸檔實現(xiàn)代碼:

//這里student、book對象初始化的代碼就不列了NSArray *stuArr =@[stu1,stu2];if([NSKeyedArchiver archiveRootObject:stuArr toFile:path5])

{

NSLog(@"寫入成功");

}

NSArray*arr = [NSKeyedUnarchiver unarchiveObjectWithFile:path5];

如此,便可以實現(xiàn)自定義對象的歸檔和解檔了。

四、NSUserDefaults

1.NSUserDefaults是一個單例類,如它的名字一樣,用于永久保存一些用戶對于應(yīng)用程序的配置之類的簡單數(shù)據(jù),其簡單而又實用

2.NSUserDefaults支持的數(shù)據(jù)類型同XML歸檔一樣,僅僅用于保存一些程序配置信息的話完全是可以勝任的。

//保存NSString *passWord =@"88888888";

NSUserDefaults*user =[NSUserDefaults standardUserDefaults];

[user setObject:passWord forKey:@"passWord"];//通過存儲時候key取出相應(yīng)的valueNSString *passWord = [ user objectForKey:@"passWord"];

3.當(dāng)然,NSUserDefaults也可以存儲自定義類,同NSKeyedArchiver歸檔相似,為自定義類實現(xiàn)

協(xié)議,然后

//將student類型變?yōu)镹SData類型 (這里采用NSKeyedArchiver中的例子Student為例)NSData *data = [NSKeyedArchiver archivedDataWithRootObject:student];

// NSUserDefaults是支持NSData類型

NSUserDefaults *user = [NSUserDefaults standardUserDefaults];

[user setObject:data forKey:@"student"];

五、由sqlite到FMDB

1.使用sqlite之前需要了解一下基本的一些sql語句,很簡單,學(xué)會建表、增刪改查的語句就行了。(學(xué)習(xí)的話這里推薦火狐瀏覽器下的sqlite組件)

2.使用:在工程中導(dǎo)入包“l(fā)ibsqlite3.dylib”,在類中導(dǎo)入頭文件#import

Xcode7注意了,當(dāng)你去導(dǎo)入sqlite3.dylib的時候(其實那兩個.tbd文件就是以前老版本的替代了),你會發(fā)現(xiàn)根本找不到這個包,因為這個包自xcode7之后就被蘋果隱藏掉了

如果你想要使用老版本的,請繼續(xù)下面的操作。

當(dāng)點擊“+”彈出窗口之后,選擇“add other”,快捷鍵 CMD+Shift+G (Go to the folder),輸入/usr/lib后,進入隱藏的界面,在文件目錄下找到,然后添加你需要的 *.dylib,如libsqlite3.dylib文件。

3.sqlite使用,這里講一下我之前做的一個增刪改查的demo,下面貼上代碼

User類:

#import

@interfaceUser : NSObject

@property (nonatomic,retain)NSData*icon;//頭像@property (nonatomic,copy)NSString *name;//名字@property (nonatomic,copy)NSString *phone;//電話號碼@property (nonatomic,assign)intage;//年齡@property (nonatomic,assign)NSInteger ID;@end

UserDBManager類

////UserDBManager.h//Sqlite3基礎(chǔ)操作////Created by silence on 15-8-15.//Copyright (c) 2015年 hawode06. All rights reserved.//#import

#import#import"User.h"#defineinsert @"INSERT"@interfaceUserDBManager : NSObject//插入數(shù)據(jù)-(BOOL)insertUser:(User *)user;//刪除數(shù)據(jù)-(BOOL)delePerson:(NSInteger)idd;//修改數(shù)據(jù)-(BOOL)updatePerson:(User *)User;//查詢所有-(NSArray *)queryUser;//通過姓名查詢用戶-(NSArray *)searchWithName:(NSString *)str;@end////UserDBManager.m//Sqlite3基礎(chǔ)操作////Created by silence on 15-8-15.//Copyright (c) 2015年 hawode06. All rights reserved.//#import"UserDBManager.h"@interfaceUserDBManager ()

@property (nonatomic,copy)NSString*dbPath;

@property (nonatomic,assign)sqlite3*dataBase;@end@implementationUserDBManager-(BOOL)openDB

{

NSString*path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];

NSString*dbPath = [path stringByAppendingPathComponent:@"user.db"];

NSLog(@"%@",dbPath);

NSFileManager*fm =[NSFileManager defaultManager];if([fm fileExistsAtPath:dbPath])

{//如果存在就打開boolresult = sqlite3_open([dbPath UTF8String], &_dataBase) ==SQLITE_OK;if(result)

{returnYES;

}else{

sqlite3_close(_dataBase);returnNO;

}

}else{//打開數(shù)據(jù)庫 返回值sqlite_ok 代表打開成功if(sqlite3_open([dbPath UTF8String], &_dataBase) ==SQLITE_OK)

{

NSString*sql =@"create table? if not exists \"User\"(\"id\" INTEGER PRIMARY KEY? AUTOINCREMENT? NOT NULL? UNIQUE,\"name\" varchar,\"phone\" varchar,\"age\" INTEGER NOT NULL DEFAULT 1,\"image\" blob)";//執(zhí)行創(chuàng)建表的sql語句sqlite3_stmt *stateMent;//解析sql語句? 第一個 數(shù)據(jù)庫變量? 第二個sql語句? sql語句的長度 -1代表自動計算? stetement變量intpResult =? sqlite3_prepare_v2(_dataBase, [sql UTF8String], -1, &stateMent, nil);//解析sql 語句失敗if(pResult !=SQLITE_OK)

{

NSLog(@"創(chuàng)建表失敗");

}else{//執(zhí)行sql 語句 成功if(sqlite3_step(stateMent) ==SQLITE_DONE)

{

NSLog(@"創(chuàng)建表成功");

}else{

NSLog(@"創(chuàng)建表失敗");

}

}//釋放statementsqlite3_finalize(stateMent);returnYES;

}else{

sqlite3_close(_dataBase);returnNO;

}

}returnYES;

}-(BOOL)insertUser:(User *)user

{if([self openDB])

{

NSString*addSql =@"insert into User (name,phone,age,image) values (?,?,?,?)";

sqlite3_stmt*stateMent;//解析sql語句? 第一個 數(shù)據(jù)庫變量? 第二個sql語句? sql語句的長度 -1代表自動計算? stetement變量intresult = sqlite3_prepare_v2(_dataBase, [addSql UTF8String], -1, &stateMent, nil);//給sql語句里的’?‘? 賦值? 第一個參數(shù)是statement 第二個是‘?’的位置 以1開頭//姓名sqlite3_bind_text(stateMent,1, [user.name UTF8String], -1, SQLITE_TRANSIENT);//電話sqlite3_bind_text(stateMent,2, [user.phone UTF8String], -1, SQLITE_TRANSIENT);//年齡sqlite3_bind_int(stateMent,3, user.age);//頭像sqlite3_bind_blob(stateMent,4, [user.icon bytes], (int)user.icon.length, nil);if(result ==SQLITE_OK)

{//執(zhí)行sql 語句 成功if(sqlite3_step(stateMent) ==SQLITE_DONE)

{

NSLog(@"插入成功");

}else{

NSLog(@"插入失敗");

}

}//釋放statementsqlite3_finalize(stateMent);//關(guān)閉數(shù)據(jù)庫sqlite3_close(_dataBase);returnYES;

}returnNO;

}-(BOOL)delePerson:(NSInteger)idd

{if([self openDB])

{

NSString*deleSql = [NSString stringWithFormat:@"delete from User where id = %ld",idd];//通過id刪除user表中的用戶數(shù)據(jù)sqlite3_stmt *stateMent;intresult = sqlite3_prepare_v2(_dataBase, [deleSql UTF8String], -1, &stateMent, nil);if(result ==SQLITE_OK)

{//執(zhí)行sql 語句 成功if(sqlite3_step(stateMent) ==SQLITE_DONE)

{

NSLog(@"刪除成功");

}else{

NSLog(@"刪除失敗");

}

}//釋放statementsqlite3_finalize(stateMent);//關(guān)閉數(shù)據(jù)庫sqlite3_close(_dataBase);returnYES;

}returnNO;

}-(NSArray *)queryUser

{

NSMutableArray*arr;if([self openDB])

{

arr= [NSMutableArray arrayWithCapacity:0];

NSString*sql =@"select * from User";//sql 語句:查詢User表中的所有數(shù)據(jù)sqlite3_stmt *statement;//解析sql語句? 第一個 數(shù)據(jù)庫變量? 第二個sql語句? sql語句的長度 -1代表自動計算? stetement變量intpResult =? sqlite3_prepare_v2(_dataBase, [sql UTF8String], -1, &statement, nil);//解析sql語句成功if(pResult ==SQLITE_OK)

{while(sqlite3_step(statement) ==SQLITE_ROW)

{

User*user =[[User alloc] init];intnum = sqlite3_column_int(statement,0);char*cName = (char*)sqlite3_column_text(statement,1);char*cPhone = (char*)sqlite3_column_text(statement,2);intage = sqlite3_column_int(statement,3);char*iconBytes = (char*)sqlite3_column_blob(statement,4);

NSInteger iconDataLen= sqlite3_column_bytes(statement,4);

user.name=[NSString stringWithCString:cName encoding:NSUTF8StringEncoding];

user.phone=[NSString stringWithCString:cPhone encoding:NSUTF8StringEncoding];

user.age=age;

user.icon=[NSData dataWithBytes:iconBytes length:iconDataLen];

user.ID=num;

[arr addObject:user];

}//釋放statementsqlite3_finalize(statement);

}//關(guān)閉數(shù)據(jù)庫sqlite3_close(_dataBase);

}returnarr;

}-(NSArray *)searchWithName:(NSString *)str

{

NSMutableArray*arr;if([self openDB])

{

arr= [NSMutableArray arrayWithCapacity:0];

NSString*sql = [NSString stringWithFormat:@"select * from User where name like '%%%@%%'",str];

NSLog(@"sql語句:%@",sql);

sqlite3_stmt*statement;//解析sql語句? 第一個 數(shù)據(jù)庫變量? 第二個sql語句? sql語句的長度 -1代表自動計算? stetement變量intpResult =? sqlite3_prepare_v2(_dataBase, [sql UTF8String], -1, &statement, nil);//解析sql語句成功if(pResult ==SQLITE_OK)

{while(sqlite3_step(statement) ==SQLITE_ROW)

{

User*user =[[User alloc] init];intnum = sqlite3_column_int(statement,0);char*cName = (char*)sqlite3_column_text(statement,1);char*cPhone = (char*)sqlite3_column_text(statement,2);intage = sqlite3_column_int(statement,3);char*iconBytes = (char*)sqlite3_column_blob(statement,4);

NSInteger iconDataLen= sqlite3_column_bytes(statement,4);

user.name=[NSString stringWithCString:cName encoding:NSUTF8StringEncoding];

user.phone=[NSString stringWithCString:cPhone encoding:NSUTF8StringEncoding];

user.age=age;

user.icon=[NSData dataWithBytes:iconBytes length:iconDataLen];

user.ID=num;

[arr addObject:user];

}

NSLog(@"數(shù)組%@",arr);//釋放statementsqlite3_finalize(statement);

}//關(guān)閉數(shù)據(jù)庫sqlite3_close(_dataBase);

}returnarr;

}@end

// 修改用戶數(shù)據(jù)的好像當(dāng)時懶得做,并沒有實現(xiàn)那個方法,看懂了另外幾個增、查、刪的實現(xiàn)也就差不多了,基本操作數(shù)據(jù)庫的流程都一樣,只是執(zhí)行不同的sql語句而已。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容