iOS開發(fā)中本地存儲主要有三種形式
XML屬性列表(plist)歸檔
Preference(偏好設(shè)置)
NSKeyedArchiver歸檔(NSCoding)
應(yīng)用沙盒
什么是應(yīng)用沙盒
要想在本地存儲數(shù)據(jù),那就要知道一下什么是應(yīng)用沙盒
,其實很好理解應(yīng)用沙盒就是應(yīng)用的文件夾,與其他文件系統(tǒng)隔離。每一個iOS應(yīng)用都有自己的應(yīng)用沙盒,應(yīng)用必須待在自己的沙盒里,其它應(yīng)用不能訪問該沙盒。
如何獲取應(yīng)用沙盒路徑,可以通過打印NSHomeDirectory()來獲取應(yīng)用沙盒路徑,下圖為打印路徑結(jié)果:
圖片001
Melody_Zhy 是用戶文件夾(樣子是個小房子)
3CEC8EEB-C230-44BE-93B7-DF3B9A120A94
iOS8之后每次運行Xcode都會生成不同的沙盒路徑,不同之處就是最后這個文件夾名,可能是蘋果為了安全著想
應(yīng)用沙盒結(jié)構(gòu)分析
首先我們先來看下,應(yīng)用沙盒里面都有什么
圖片002
這里提一下Finder的快捷鍵 shift + com + g
可以前往任意路徑的文件夾,因此我們可以打印沙盒路徑之后將沙盒路徑復(fù)制到Finder前往路徑文件夾中,前往應(yīng)用沙盒。這是一個比較耽誤事的方法!幸好有一款叫做simpholders的app,它可以很簡單的訪問應(yīng)用的沙盒路徑,記得去下載simpholders2哦,第一代iOS8之后就不能用了,app很簡單易懂,用下就會了~
現(xiàn)在我們來看看應(yīng)用沙盒里面這些文件夾都是做什么用的
Documents :保存應(yīng)用運行時生成的需要持久化的數(shù)據(jù),iTunes同步設(shè)備時會備份該目錄。例如,游戲應(yīng)用可將游戲存檔保存在該目錄
Library/Caches :
保存應(yīng)用運行時生成的需要持久化的數(shù)據(jù),iTunes同步設(shè)備時不會備份該目錄。一般存儲體積大、不需要備份的非重要數(shù)據(jù)
Library/Preference :
保存應(yīng)用的所有偏好設(shè)置,iOS的Settings(設(shè)置)應(yīng)用會在該目錄中查找應(yīng)用的設(shè)置信息。iTunes同步設(shè)備時會備份該目錄
tmp :
保存應(yīng)用運行時所需的臨時數(shù)據(jù),使用完畢后再將相應(yīng)的文件從該目錄刪除。應(yīng)用沒有運行時,系統(tǒng)也可能會清除該目錄下的文件。iTunes同步設(shè)備時不會備份該目錄
應(yīng)用沙盒目錄的常見獲取方式
沙盒根目錄的獲取方式
正如上面我們所說:
NSString *home = NSHomeDirectory();
Documents文件夾的獲取方式(3種)
第一種( !笨!)
// 利用沙盒根目錄拼接字符串
NSString *homePath = NSHomeDirectory();
NSString *docPath = [homePath stringByAppendingString:@"/Documents"];
第二種( !還??!)
// 利用沙盒根目錄拼接”Documents”字符串
NSString *homePath = NSHomeDirectory();
NSString *docPath = [homePath
stringByAppendingPathComponent:@"Documents"];
但是不建議使用這種方法,因為不定哪天蘋果大大就把文件名稱改了呢-_-!
第三種( !~推薦~ !)
// NSDocumentDirectory 要查找的文件
// NSUserDomainMask 代表從用戶文件夾下找
// 在iOS中,只有一個目錄跟傳入的參數(shù)匹配,所以這個集合里面只有一個元素
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES)[0];
NSString *filePath = [path
stringByAppendingPathComponent:@"xxx.plist"];
這里我來詳細的說下NSSearchPathForDirectoriesInDomains這個方法的幾個參數(shù) :
<#NSSearchPathDirectory directory#> 這個參數(shù)代表要查找的文件,是個枚舉!
枚舉你懂的點擊去看看就知道了~
<#NSSearchPathDomainMask domainMask#> 這個參數(shù)代表從用戶文件夾下找,也是枚舉!
最后一個參數(shù)如果是NO的話,打印的路徑會是這種形式~/Documents,我們一般都會用YES,這樣可以獲取完整路徑字符串!
這個方法的返回值是一個數(shù)組,但在iOS中,只有一個目錄跟傳入的參數(shù)匹配,所以這個集合里面只有一個元素,所以我們?nèi)〉谝粋€元素!
Library/Caches文件夾的獲取方式(跟上面的方法相似)
這里我只用上面的第三種方法!注意第一個參數(shù)!
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES)[0];
NSString *filePath = [path
stringByAppendingPathComponent:@"student.data"];
tmp文件夾的獲取方式
NSString *tmp= NSTemporaryDirectory();
Library/Preference文件夾的獲取方式
通過NSUserDefaults類存取該目錄下的設(shè)置信息!
!!!這個下面會有介紹!!!
XML屬性列表(plist)歸檔
plist文件
plist的根Type只能是字典(NSDictionary)或者是數(shù)組(NSArray)所以歸檔時我們只能將數(shù)組或字典保存到plist文件中,但是NSString也能通過歸檔保存到plist文件中同時它也可以通過stringWithContentsOfFile解檔,它保存到plist中時Type是空的,Value是有值的!
plist文件的歸檔
NSArray *arr = [[NSArray alloc] initWithObjects:@"1", @"2", nil];
// NSDocumentDirectory 要查找的文件
// NSUserDomainMask 代表從用戶文件夾下找
// 在iOS中,只有一個目錄跟傳入的參數(shù)匹配,所以這個集合里面只有一個元素
NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,
NSUserDomainMask, YES)[0];
NSString *filePath = [path
stringByAppendingPathComponent:@"xxx.plist"];
[arr writeToFile:filePath atomically:YES];
plist文件的解檔
NSString *filePath = [path
stringByAppendingPathComponent:@"xxx.plist"];
// 解檔
NSArray *arr = [NSArray arrayWithContentsOfFile:filePath];
NSLog(@"%@", arr);
Preference(偏好設(shè)置)
OC中有一個NSUserDefaults的單例,它可以用來存儲用戶的偏好設(shè)置,例如:用戶名,字體的大小,用戶的一些設(shè)置等,下面我用兩個UISwitch來演示如何保存用戶設(shè)置開關(guān)的關(guān)閉狀態(tài)
保存用戶偏好設(shè)置
// 獲取用戶偏好設(shè)置對象
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// 保存用戶偏好設(shè)置
[defaults setBool:self.one.isOn forKey:@"one"];
[defaults setBool:self.two.isOn forKey:@"two"];
//
注意:UserDefaults設(shè)置數(shù)據(jù)時,不是立即寫入,而是根據(jù)時間戳定時地把緩存中的數(shù)據(jù)寫入本地磁盤。所以調(diào)用了set方法之后數(shù)據(jù)有可能還沒有寫入磁盤應(yīng)用程序就終止了。
// 出現(xiàn)以上問題,可以通過調(diào)用synchornize方法強制寫入
// 現(xiàn)在這個版本不用寫也會馬上寫入 不過之前的版本不會
[defaults synchronize];
讀取用戶偏好設(shè)置
// 讀取用戶偏好設(shè)置
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
self.one.on = [defaults boolForKey:@"one"];
self.two.on = [defaults boolForKey:@"two"];
NSKeyedArchiver歸檔(NSCoding)
只有遵守了NSCoding協(xié)議的類才可以用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔,如果對象是NSString、NSDictionary、NSArray、NSData、NSNumber等類型,可以直接用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔~
下面我舉的??是歸檔解檔一個Student模型,因此該模型應(yīng)該遵守NSCoding協(xié)議
實現(xiàn)encodeWithCoder和initWithCoder方法
- (void)encodeWithCoder:(NSCoder *)coder
{
[coder encodeObject:self.name forKey:@"name"];
[coder encodeInteger:self.age forKey:@"age"];
}
- (instancetype)initWithCoder:(NSCoder *)coder
{
self = [super init];
if (self) {
self.age = [coder decodeIntegerForKey:@"age"];
self.name = [coder decodeObjectForKey:@"name"];
}
return self;
}
歸檔
Student *s1 = [[Student alloc] init];
s1.name = @"zzz";
s1.age = 18;
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES)[0];
// 這個文件后綴可以是任意的,只要不與常用文件的后綴重復(fù)即可,我喜歡用data
NSString *filePath = [path
stringByAppendingPathComponent:@"student.data"];
// 歸檔
[NSKeyedArchiver archiveRootObject:s1 toFile:filePath];
解檔
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory,
NSUserDomainMask, YES)[0];
NSString *filePath = [path
stringByAppendingPathComponent:@"student.data"];
// 解檔
Student *s = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@----%ld", s.name, s.age);
這就是我想到的iOS開發(fā)中本地數(shù)據(jù)存儲的幾種方式,希望對大家有幫助~ 藍鷗iOS開發(fā),國內(nèi)口碑最好的iOS培訓(xùn)學(xué)院,詳情請咨詢官方網(wǎng)站http://www.lanou3g.com我們是一群熱愛IT的年輕人,如果你也愛IT、愛iOS開發(fā),歡迎前來藍鷗iPhone培訓(xùn)中心參觀學(xué)習(xí),讓我們共同為夢想發(fā)聲。