前言
一、直接寫入(writeToFile)
1.使用場景
- 生成plist文件,以字典的形式保存簡單配置信息,如info.plist。
- 將UIImage壓縮之后,轉化為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.優勢
- 讀寫語法簡單
4.劣勢
- writeFile方法只能寫入 NSData, NSDate, NSNumber, NSString, NSArray, 和 NSDictionary的實例
- 只能一次性寫入、讀出
二、NSUserDefaults
NSUserDefaults原理也是通過鍵值對形式將信息保存到plist文件中,存儲路徑為<Application_Home>/Library/Preferences
1.使用場景
- 存取偏好設置,如用戶名、個性化設置等
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更改了數據之后,并非立即寫入磁盤,而是根據時間戳定時寫入,若App閃退,則數據可能丟失。所以,如果是比較重要的數據,則需再調用[defaults synchronize],使更改立即生效。但,調用這個方法之后那些沒被修改的值也會更新,所以建議在App即將退出時調用即可。
3.優勢
- 存取方便,無需維護文件路徑
- 單例,線程安全
三、NSKeyedArchiver
1.使用場景
- 存儲自定義對象模型,將服務端下發的數據存儲到本地,用作備份或者緩存
- 歸檔的對象是Foundation框架中的對象.我們不可能對UIImage進行歸檔
- 歸檔是將對象轉換為字節碼,以加密的形式存儲在磁盤上,文件名后綴可隨意定義
2.使用方法
- 對象需要實現NSCoding協議,并實現下面兩個方法
- (void)encodeWithCoder:(NSCoder *)coder {
#if 父類實現了NSCoding協議
[super encodeWithCoder:coder];
[coder encodeObject:_name forKey:name];
[coder encodeInt:_age forKey:age];
}
- (id)initWithCoder:(NSCoder *)decoder {
#if 父類實現了NSCoding協議
self = [super initWithCoder:decoder];
#else 父類實現了NSCoding協議
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.優勢
- 能夠存取自定義數據
4.劣勢
- 不能讀寫較大數據量。NSKeyedArchiver是一次性讀寫數據,若數據量較大,則會降低讀寫速度。
四、SQLite3
1.簡介
-
基于C語言編寫的嵌入式數據庫,能夠存儲大量數據
1.打開數據庫 int sqlite3_open( const char *filename, // 數據庫的文件路徑 sqlite3 **ppDb // 數據庫實例 ); 2.執行任何SQL語句 int sqlite3_exec( sqlite3*, // 一個打開的數據庫實例 const char *sql, // 需要執行的SQL語句 int (*callback)(void*,int,char**,char**), // SQL語句執行完畢后的回調 void *, // 回調函數的第1個參數 char **errmsg // 錯誤信息 ); 3.檢查SQL語句的合法性(查詢前的準備) int sqlite3_prepare_v2( sqlite3 *db, // 數據庫實例 const char *zSql, // 需要檢查的SQL語句 int nByte, // SQL語句的最大字節長度 sqlite3_stmt **ppStmt, // sqlite3_stmt實例,用來獲得數據庫數據 const char **pzTail ); 4.查詢一行數據 int sqlite3_step(sqlite3_stmt*); // 如果查詢到一行數據,就會返回 SQLITE_ROW 5.利用stmt獲得某一字段的值(字段的下標從0開始) double sqlite3_column_double(sqlite3_stmt*, int iCol); // 浮點數據 int sqlite3_column_int(sqlite3_stmt*, int iCol); // 整型數據 sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol); // 長整型數據 const void *sqlite3_column_blob(sqlite3_stmt*, int iCol); // 二進制文本數據 const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol); // 字符串數據
2.使用方法
- 打開數據庫
利用sqlite3_open()打開數據庫會指定一個數據庫文件保存路徑,如果文件存在則直接打開,否則創建并打開。打開數據庫會得到一個sqlite3類型的對象,后面需要借助這個對象進行其他操作。 - 執行SQL語句,執行SQL語句又包括有返回值的語句和無返回值語句。
- 對于無返回值的語句(如增加、刪除、修改等)直接通過sqlite3_exec()函數執行;
- 對于有返回值的語句則首先通過sqlite3_prepare_v2()進行sql語句評估(語法檢測),然后通過sqlite3_step()依次取出查詢結果的每一行數據,對于每行數據都可以通過對應的sqlite3column類型()方法獲得對應列的數據,如此反復循環直到遍歷完成。
3.優勢
- 方便移植,高效率的增刪改查,內存消耗小
4.劣勢
- 需要使用C語言語法使用數據庫,不容易上手。
五、FMDB
1.簡介
- SQLite3框架,提供object-C語言API,保證了多線程數據操作安全。
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.優勢
- 避免了多余的C語言代碼
- 比CoreData更加靈活,屬于輕量級框架
- FMDataBaseQueue保證了多線程操作的安全性
六、Core Data
1.使用場景
CoreData也是使用數據庫存儲數據量比較大,跟業務耦合度的較高的數據。本質上CoreData是對SQLite數據庫的封裝。
Core Data框架提供了對象-關系映射(ORM)的功能,即能夠將OC對象轉化成數據,保存在SQLite3數據庫文件中,也能夠將保存在數據庫中的數據還原成OC對象。
2.優勢
- 內存消耗小,不用直接編輯SQL語句
3.劣勢
- 基于SQLite,性能上劣于SQLite
- 架構非并發安全,多線程下使用會出現一些問題
- 使用過程較為繁瑣,業界使用FMDB較多一些
六、Key-Chain
1.使用場景
- 加密存儲密碼、令牌等敏感性小數據,重裝App時會保留之前的數據,可實現自動填充
- 本質是一個sqlite數據庫,位于/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.優勢
- 會對數據進行加密,安全性高
- 不會隨App卸載而丟失,可在App重裝時獲取部分信息
- 數據存在與App沙盒之外,通過分組能使App間共享數據
參考
iOS 數據存儲的常用方式
iOS存儲介紹
iOS 中數據持久化的幾種方式
iOS應用架構談 本地持久化方案及動態部署
iOS SQLite
iOS Core Data
IOS開發之iCloud開發(數據與文檔的讀寫刪除)