前言
一料睛、直接寫入(writeToFile)
1.使用場景
- 生成plist文件冗疮,以字典的形式保存簡單配置信息,如info.plist损趋。
- 將UIImage壓縮之后,轉(zhuǎn)化為NSData椅寺,存在本地浑槽。
2.使用方法
1)寫 - writeFile:atomically:
- NSDictionary, NSArray, NSString, NSData
NSString *filePath = [[self getDocumentPath] stringByAppendingString:@"file.plist"];
NSDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:@"a", @"key", nil];
[dictionary writeToFile:filePath atomically:YES];
2)讀 - initWithContentsOfFile:
- NSDictionary, NSArray, NSString, NSData
NSString *filePath = [[self getDocumentPath] stringByAppendingString:@"file.plist"];
NSDictionary *dictionary = [NSDictionary alloc] initWithContentsOfFile:filePath];
initWithContentsOfFile:是比較通用的初始化方法蒋失。NSArray,NSDictionary有自己的類初始化方法桐玻,arrayWithContentsOfFile:和 dictionaryWithContentsOfFile:
3.優(yōu)勢
- 讀寫語法簡單
4.劣勢
- writeFile方法只能寫入 NSData, NSDate, NSNumber, NSString, NSArray, 和 NSDictionary的實(shí)例
- 只能一次性寫入篙挽、讀出
二、NSUserDefaults
NSUserDefaults原理也是通過鍵值對形式將信息保存到plist文件中镊靴,存儲路徑為<Application_Home>/Library/Preferences
1.使用場景
- 存取偏好設(shè)置铣卡,如用戶名、個性化設(shè)置等
2.使用方法
獲取共享單例
NSUserDefaults *defautls = [NSUserDefaults standardUserDefaults];
1)存
[defaults setObject:@"stringValue" forKey:@"keyName"];
[defaults setBool:YES forKey:@"AllowVoice"];
2)取
[defaults objectForKey:@"keyName"];
[defaults boolForKey:@"AllowVoice"];
3)刪
[defaults removeObjectForKey:@"AllowVoice"];
NSUserDefaults更改了數(shù)據(jù)之后偏竟,并非立即寫入磁盤煮落,而是根據(jù)時間戳定時寫入,若App閃退苫耸,則數(shù)據(jù)可能丟失州邢。所以儡陨,如果是比較重要的數(shù)據(jù)褪子,則需再調(diào)用[defaults synchronize],使更改立即生效骗村。但嫌褪,調(diào)用這個方法之后那些沒被修改的值也會更新,所以建議在App即將退出時調(diào)用即可胚股。
3.優(yōu)勢
- 存取方便笼痛,無需維護(hù)文件路徑
- 單例,線程安全
三琅拌、NSKeyedArchiver
1.使用場景
- 存儲自定義對象模型缨伊,將服務(wù)端下發(fā)的數(shù)據(jù)存儲到本地,用作備份或者緩存
- 歸檔的對象是Foundation框架中的對象.我們不可能對UIImage進(jìn)行歸檔
- 歸檔是將對象轉(zhuǎn)換為字節(jié)碼进宝,以加密的形式存儲在磁盤上刻坊,文件名后綴可隨意定義
2.使用方法
- 對象需要實(shí)現(xiàn)NSCoding協(xié)議,并實(shí)現(xiàn)下面兩個方法
- (void)encodeWithCoder:(NSCoder *)coder {
#if 父類實(shí)現(xiàn)了NSCoding協(xié)議
[super encodeWithCoder:coder];
[coder encodeObject:_name forKey:name];
[coder encodeInt:_age forKey:age];
}
- (id)initWithCoder:(NSCoder *)decoder {
#if 父類實(shí)現(xiàn)了NSCoding協(xié)議
self = [super initWithCoder:decoder];
#else 父類實(shí)現(xiàn)了NSCoding協(xié)議
self = [super init]党晋;
if (self) {
_name = [decoder decodeObjectForKey:name];
_age = [decoder decodeIntForKey:age];
}
return self;
} - 歸檔
[NSKeyedArchiver archiveRootObject: self.model toFile:KFilePath]; - 解檔
self.model = [NSKeyedUnarchiver unarchiveObjectWithFile:KFilePath];
3.優(yōu)勢
- 能夠存取自定義數(shù)據(jù)
4.劣勢
- 不能讀寫較大數(shù)據(jù)量谭胚。NSKeyedArchiver是一次性讀寫數(shù)據(jù),若數(shù)據(jù)量較大未玻,則會降低讀寫速度灾而。
四、SQLite3
1.簡介
-
基于C語言編寫的嵌入式數(shù)據(jù)庫扳剿,能夠存儲大量數(shù)據(jù)
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ù)
2.使用方法
- 打開數(shù)據(jù)庫
利用sqlite3_open()打開數(shù)據(jù)庫會指定一個數(shù)據(jù)庫文件保存路徑庇绽,如果文件存在則直接打開锡搜,否則創(chuàng)建并打開癣猾。打開數(shù)據(jù)庫會得到一個sqlite3類型的對象,后面需要借助這個對象進(jìn)行其他操作余爆。 - 執(zhí)行SQL語句纷宇,執(zhí)行SQL語句又包括有返回值的語句和無返回值語句。
- 對于無返回值的語句(如增加蛾方、刪除像捶、修改等)直接通過sqlite3_exec()函數(shù)執(zhí)行;
- 對于有返回值的語句則首先通過sqlite3_prepare_v2()進(jìn)行sql語句評估(語法檢測)桩砰,然后通過sqlite3_step()依次取出查詢結(jié)果的每一行數(shù)據(jù)拓春,對于每行數(shù)據(jù)都可以通過對應(yīng)的sqlite3column類型()方法獲得對應(yīng)列的數(shù)據(jù),如此反復(fù)循環(huán)直到遍歷完成亚隅。
3.優(yōu)勢
- 方便移植硼莽,高效率的增刪改查,內(nèi)存消耗小
4.劣勢
- 需要使用C語言語法使用數(shù)據(jù)庫煮纵,不容易上手懂鸵。
五、FMDB
1.簡介
- SQLite3框架行疏,提供object-C語言API匆光,保證了多線程數(shù)據(jù)操作安全。
2.使用方法
-
查詢
[_dataBase open];
NSMutableArray *dataArray = [[NSMutableArray alloc] init];
FMResultSet *res = [_dataBase executeQuery:@"SELECT * FROM Phone"];while ([res next]) { PhoneModel *phoneModel = [[PhoneModel alloc] init]; phoneModel.uniqueId = [res intForColumn:@"phone_id"]; phoneModel.name = [res stringForColumn:@"phone_name"]; phoneModel.price = [res intForColumn:@"phone_price"]; [dataArray addObject:phoneModel]; } [_dataBase close];
增加
[_dataBase open];
BOOL result = [_dataBase executeUpdate:@"INSERT INTO Phone(phone_name,phone_price)VALUES(?,?)",phoneModel.name, @(phoneModel.price)];
[_dataBase close];修改
[_dataBase open];
BOOL result;
[_dataBase executeUpdate:@"UPDATE 'Phone' SET phone_name = ? WHERE phone_id = ? ",newName,@(phoneId)];
result = [_dataBase executeUpdate:@"UPDATE 'Phone' SET phone_price = ? WHERE phone_id = ? ",@(newPrice),@(phoneId)];
[ _dataBase close];刪除
[_dataBase open];
BOOL result = [_dataBase executeUpdate:@"DELETE FROM Phone WHERE phone_id = ?",@(phoneId)];
[_dataBase close];
3.優(yōu)勢
- 避免了多余的C語言代碼
- 比CoreData更加靈活酿联,屬于輕量級框架
- FMDataBaseQueue保證了多線程操作的安全性
六终息、Core Data
1.使用場景
CoreData也是使用數(shù)據(jù)庫存儲數(shù)據(jù)量比較大,跟業(yè)務(wù)耦合度的較高的數(shù)據(jù)贞让。本質(zhì)上CoreData是對SQLite數(shù)據(jù)庫的封裝周崭。
Core Data框架提供了對象-關(guān)系映射(ORM)的功能,即能夠?qū)C對象轉(zhuǎn)化成數(shù)據(jù)喳张,保存在SQLite3數(shù)據(jù)庫文件中续镇,也能夠?qū)⒈4嬖跀?shù)據(jù)庫中的數(shù)據(jù)還原成OC對象。
2.優(yōu)勢
- 內(nèi)存消耗小蹲姐,不用直接編輯SQL語句
3.劣勢
- 基于SQLite磨取,性能上劣于SQLite
- 架構(gòu)非并發(fā)安全,多線程下使用會出現(xiàn)一些問題
- 使用過程較為繁瑣柴墩,業(yè)界使用FMDB較多一些
六忙厌、Key-Chain
1.使用場景
- 加密存儲密碼、令牌等敏感性小數(shù)據(jù)江咳,重裝App時會保留之前的數(shù)據(jù)逢净,可實(shí)現(xiàn)自動填充
- 本質(zhì)是一個sqlite數(shù)據(jù)庫,位于/private/var/Keychains/keychain-2.db
2.使用方法
// 查詢
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef *result);
// 添加
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef *result);
// 更新
KeyChain中的ItemOSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate);
// 刪除
KeyChain中的ItemOSStatus SecItemDelete(CFDictionaryRef query)
3.優(yōu)勢
- 會對數(shù)據(jù)進(jìn)行加密,安全性高
- 不會隨App卸載而丟失爹土,可在App重裝時獲取部分信息
- 數(shù)據(jù)存在與App沙盒之外甥雕,通過分組能使App間共享數(shù)據(jù)
參考
iOS 數(shù)據(jù)存儲的常用方式
iOS存儲介紹
iOS 中數(shù)據(jù)持久化的幾種方式
iOS應(yīng)用架構(gòu)談 本地持久化方案及動態(tài)部署
iOS SQLite
iOS Core Data
IOS開發(fā)之iCloud開發(fā)(數(shù)據(jù)與文檔的讀寫刪除)