iOS-關於數據持久化不看我看誰(一)
前言
我們老是有一種一年到頭來發現自己什麼都沒有干,一年就這樣過去了。自從關注了一個叫曉多的筆者,裡面有太多勵志的心靈雞湯,為此我從文章中也學到了很多,其實我覺得對生命的不浪費就是努力成就更好的自己,也不枉在人間走這一朝。
目錄
一、什麼是持久化
二、沙盒是什麼
2.1 沙盒簡介及獲取沙盒路徑
2.2 Documents
2.2 Library
2.2.1 Caches
2.2.2 Preferences
2.3 SystemData
2.4 tmp
三、數據持久化的幾種方式
3.1 property list(屬性列表)
3.2 Preference(偏好設置)
3.3 NSKeyedArchiver(歸檔)
3.4 SQLite3/FMDB(嵌入式資料庫)
3.5 CoreData(面向對象的嵌入式資料庫)
~ 注意:SQLite3/FMDB以及CoreData要說的東西很多將在下章繼續
一、什麼是持久化
所謂的持久化,就是將數據保存到硬碟中,使得在應用程序或機器重啟後可以繼續訪問之前保存的數據。
二、沙盒是什麼
2.1 沙盒簡介及獲取沙盒路徑
沙盒(sandbox):每一個App都有一個存儲空間。iOS系統為每個應用程序創建自己的目錄,每個應用程序只能訪問自己的目錄,不能相互通信。
簡單粗俗一點來說:沙盒就是存儲app所有的數據的路徑,且默認情況下只能訪問程序自己的目錄
iOS沙盒主要包括下面幾個文件:
獲取沙盒目錄路徑
NSLog(@"%@",NSHomeDirectory());
注意: 每次編譯運行都會生成一個新的沙盒路徑,而真機不會生成新的沙盒。
2.2 Documents
保存持久化數據,會備份。一般用來存儲需要持久化的數據。
一般我們在項目中,我們會吧一些用戶的登錄信息進行存儲,以及搜索歷史記錄等等一些關鍵數據。
//獲取Documents目錄路徑
NSString *document = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
2.2 Library
Library裡面包含兩個文件夾(Caches和Preferences)
2.2.1 Caches
緩存,iTunes不會備份該目錄。內存不足時會被清除,應用沒有運行時,可能會被清除,。一般存儲體積大、不需要備份的非重要數據。
2.2.2 Preferences
保存持久化數據,會備份NSUserDefaults默認存放在此文件夾
2.3 SystemData
SystemData:去年還是沒有這個文件夾的,今天寫這篇文章時打開沙盒一看,發現居然多了SystemData這個文件夾,剛開始以為只有這個才有,然後查看好幾個別的沙盒路徑,發現都多了一個SystemData文件夾。於是乎各種百度,發現網上沒有這個的細聊,幾乎都是這樣的話語,要麼就是沒有提到這玩意。
到最後始終沒有找到我想要的答案。於是憑著自己的理解和開發經驗對此進行琢磨和滲透。
字眼的意思是存放系統的一些數據,從NSCachesDirectory和NSDocumentDirectory試探猜測是否存在一個NSSystem...開頭。從NSCachesDirectory進入頭文件去查找相關的例如NSSystem...開頭的並沒有 。
能怎麼辦,各種百度翻牆都沒有找到該東西的解釋,最後去官方文獻中各種翻資料,仍舊是一所所獲。。最後結論可能是這東西可能不是很重要吧。。
2.4 tmp
臨時文件夾
iTunes不會備份這個目錄,用來保存臨時數據,應用退出時會清除該目錄下的數據。
// 獲取tmp目錄路徑
NSString *tmp = NSTemporaryDirectory();
一般開發者需要臨時保存的數據但不需要長期保留使用可以放到此文件夾
三、數據存儲的幾種方式
3.1 property list(屬性列表)
只能存儲系統自帶的數據類型,一般實際開發中存儲字典、數組,自定義的模型無法進行存儲
#define kUserPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"latestQuery.plist"]
- (IBAction)plistSaveOnClick:(id)sender {
// NSMutableDictionary *dic = [NSMutableDictionary dictionary];
// [dic setObject:@"小明" forKey:@"name"];
// //將字典持久化到Documents/
// [dic writeToFile:path atomically:YES];
NSArray *arr = @[@"123",@"咋啦"];
/**
1、獲取應用的文件夾(應用沙盒)
NSSearchPathDirectory 搜索的目錄
NSSearchPathDomainMask 搜索範圍 NSUserDomainMask:表示在用戶的手機上查找
expandTilde 是否展開全路徑~ 如果沒有展開,應用的沙盒路徑就是~
存儲一定要展開路徑 如果要存東西 必須要是YES
*/
//YES:///Users/huahua/Library/Developer/CoreSimulator/Devices/0FB528AF-C34D-4F64-A723-6129E3FF3964/data/Containers/Data/Application/6FEDA2B8-40C2-40EA-9685-FE6DC828D7D2/Library/Caches
//NO: ~/Library/Caches
self.saveLabel.text = [NSString stringWithFormat:@"%@",arr];
[arr writeToFile:kUserPath atomically:YES];
}
- (IBAction)plistReadOnClick:(id)sender {
NSArray *arr = [NSArray arrayWithContentsOfFile:kUserPath];
self.readLabel.text = [NSString stringWithFormat:@"%@ ",arr];
NSLog(@"%@",arr);
}
3.2 Preference(偏好設置)
只能存儲系統自帶的數據類型,自定義的對象無法存儲
NSUserDefaults就是默認存放在此文件夾下面,如下案例代碼
/**
偏好設置好處:
1.不需要關心文件名(不需要設置路徑)
2.鍵值對存儲(賬號相關信息) 對象存儲
底層實現原理就是封裝了一個字典
*/
- (IBAction)userDefaultsSaveOnClick:(id)sender {
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
//放到緩存里,並不會馬上放到文件裡面
[userDefaults setObject:@"123" forKey:@"account"]; //對象
[userDefaults setObject:@"123456" forKey:@"pwd"];
//BOOL類型
[userDefaults setBool:YES forKey:@"status"];
//在ios7 默認不會馬上跟硬碟同步 同步操作 起到立即存儲的作用
[userDefaults synchronize];
self.saveLabel.text = [NSString stringWithFormat:@"account:%@ pwd:%@",[[NSUserDefaults standardUserDefaults]objectForKey:@"account"],[[NSUserDefaults standardUserDefaults]objectForKey:@"pwd"]];
}
- (IBAction)userDefaultsReadOnClick:(id)sender {
NSString *account = [[NSUserDefaults standardUserDefaults]objectForKey:@"account"];
NSString *pwd = [[NSUserDefaults standardUserDefaults]objectForKey:@"pwd"];
NSLog(@"偏好設置---賬號:%@ 密碼:%@",account,pwd);
self.readLabel.text = [NSString stringWithFormat:@"account:%@ pwd:%@",account,pwd];
}
- (IBAction)clearOnClick:(id)sender {
NSUserDefaults *userDefalits = [NSUserDefaults standardUserDefaults];
[userDefalits removeObjectForKey:@"account"];
[userDefalits removeObjectForKey:@"pwd"];
[userDefalits synchronize];
}
GIF
3.3 NSKeyedArchiver(歸檔)
/************UserManager.h****************/
@interface UserManager : NSObject
@property (nonatomic, assign) int ID;
@property(nonatomic,copy)NSString *account;
@property(nonatomic,copy)NSString *pwd;
@property(nonatomic,assign)int age;
//自定義的歸檔保存數據的方法
+(void)saveUser:(UserManager *)user;
//自定義的讀取沙盒中解檔出的數據
+(UserManager *)getUser;
/************UserManager.m****************/
#import "UserManager.h"
@implementation UserManager
/** 什麼時候調用:自定義對象歸檔的時候
作用:用來描述當前對象裡面的哪些屬性要歸檔
aCoder:用來歸檔
*/
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_account forKey:@"account"];
[aCoder encodeInteger:_age forKey:@"age"];
}
/** 什麼時候調用:解檔對象的時候調用
作用:用來描述當前對象裡面的哪些屬性要解檔*/
- (instancetype)initWithCoder:(NSCoder *)coder{
if (self = [super init]) {
//注意一定要給成員變數賦值保存起來
_account = [aDecoder decodeObjectForKey:@"account"];
_age = [aDecoder decodeIntForKey:@"age"];
return self;
}
//自定義的歸檔保存數據的方法
+(void)saveUser:(UserManager *)user{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path=[docPath stringByAppendingPathComponent:@"UserInfo.plist"];
[NSKeyedArchiver archiveRootObject:user toFile:path];
}
//自定義的讀取沙盒中解檔出的數據
+(UserManager *)getUser{
NSString *docPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
NSString *path=[docPath stringByAppendingPathComponent:@"UserInfo.plist"];
UserManager *user = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
return user;
}
@end
/************ViewController.m****************/
#pragma mark - NSKeyedArchiver(歸檔)
/** 自定義對象想要歸檔,則自定義對象必須遵守NSCoding協議,實現協議方法 */
- (IBAction)keyedArchiverSaveOnClick:(id)sender {
UserManager *userInfo = [[UserManager alloc]init];
userInfo.age = 15;
[UserManager saveUser:userInfo];
self.saveLabel.text = [NSString stringWithFormat:@"%@ %zd",userInfo.account,userInfo.age];
}
- (IBAction)keyedArchiverReadOnClick:(id)sender {
UserManager *userInfo = [UserManager getUser];
NSLog(@"NSKeyedArchiver歸檔-----賬號:%@---年齡:%d",userInfo.account,userInfo.age);
self.readLabel.text = [NSString stringWithFormat:@"%@ %zd",userInfo.account,userInfo.age];
}
※iOS 如何進行網路測速
※接手一個負分的 iOS 項目後我做了什麼
TAG:Cocoa開發者社區 |