標籤:
p1:
iOS開發中本機存放區主要有三種形式
- XML屬性列表(plist)歸檔
- Preference(喜好設定)
- NSKeyedArchiver歸檔(NSCoding)
應用沙箱
什麼是應用沙箱
要想在本機存放區資料,那就要知道一下什麼是應用沙箱 ,其實很好理解應用沙箱就是應用的檔案夾,與其他檔案系統隔離。每一個iOS應用都有自己的應用沙箱,應用必須待在自己的沙箱裡,其它應用不能訪問該沙箱。
如何擷取應用沙箱路徑,可以通過列印NSHomeDirectory()來擷取應用沙箱路徑,為列印路徑結果:
螢幕快照 2015-12-03 22.10.07.png
Melody_Zhy 是使用者檔案夾(樣子是個小房子)
3CEC8EEB-C230-44BE-93B7-DF3B9A120A94 iOS8之後每次運行Xcode都會產生不同的沙箱路徑,不同之處就是最後這個檔案夾名,可能是蘋果為了安全著想
應用沙箱結構分析
首先我們先來看下,應用沙箱裡面都有什麼
螢幕快照 2015-12-03 22.27.50.png
這裡提一下Finder的快速鍵 shift + com + g 可以前往任意路徑的檔案夾,因此我們可以列印沙箱路徑之後將沙箱路徑複製到Finder前往路徑檔案夾中,前往應用沙箱。這是一個比較耽誤事的方法!幸好有一款叫做simpholders的app,它可以很簡單的訪問應用的沙箱路徑,記得去下載simpholders2哦,第一代iOS8之後就不能用了,app很簡單易懂,用下就會了~
現在我們來看看應用沙箱裡面這些檔案夾都是做什麼用的
- Documents :儲存應用運行時產生的需要持久化的資料,iTunes同步裝置時會備份該目錄。例如,遊戲應用可將遊戲存檔儲存在該目錄
- Library/Caches : 儲存應用運行時產生的需要持久化的資料,iTunes同步裝置時不會備份該目錄。一般儲存體積大、不需要備份的非重要資料
- Library/Preference : 儲存應用的所有喜好設定,iOS的Settings(設定)應用會在該目錄中尋找應用的設定資訊。iTunes同步裝置時會備份該目錄
- tmp : 儲存應用運行時所需的臨時資料,使用完畢後再將相應的檔案從該目錄刪除。應用沒有運行時,系統也可能會清除該目錄下的檔案。iTunes同步裝置時不會備份該目錄
應用沙箱目錄的常見擷取方式
沙箱根目錄的擷取方式
正如上面我們所說:
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中,只有一個目錄跟傳入的參數匹配,所以這個集合裡面只有一個元素NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];NSString *filePath = [path stringByAppendingPathComponent:@"xxx.plist"];
這裡我來詳細的說下NSSearchPathForDirectoriesInDomains這個方法的幾個參數 :
<#NSSearchPathDirectory directory#> 這個參數代表要尋找的檔案,是個枚舉! 枚舉你懂的點擊去看看就知道了~
<#NSSearchPathDomainMask domainMask#> 這個參數代表從使用者檔案夾下找,也是枚舉!
最後一個參數如果是NO的話,列印的路徑會是這種形式~/Documents,我們一般都會用YES,這樣可以擷取完整路徑字串!
這個方法的傳回值是一個數組,但在iOS中,只有一個目錄跟傳入的參數匹配,所以這個集合裡面只有一個元素,所以我們取第一個元素!
Library/Caches檔案夾的擷取方式(跟上面的方法相似)
這裡我只用上面的第三種方法!注意第一個參數!
NSString *path = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];NSString *filePath = [path stringByAppendingPathComponent:@"student.data"];
tmp檔案夾的擷取方式
NSString *tmp= NSTemporaryDirectory();
Library/Preference檔案夾的擷取方式
通過NSUserDefaults類存取該目錄下的設定資訊!
!!!這個下面會有介紹!!!
XML屬性列表(plist)歸檔
plist檔案
plist的根Type只能是字典(NSDictionary)或者是數組(NSArray)所以歸檔時我們只能將數組或字典儲存到plist檔案中,但是NSString也能通過歸檔儲存到plist檔案中同時它也可以通過stringWithContentsOfFile解檔,它儲存到plist中時Type是空的,Value是有值的!
plist檔案的歸檔
NSArray *arr = [[NSArray alloc] initWithObjects:@"1", @"2", nil];// NSDocumentDirectory 要尋找的檔案// NSUserDomainMask 代表從使用者檔案夾下找// 在iOS中,只有一個目錄跟傳入的參數匹配,所以這個集合裡面只有一個元素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(喜好設定)
OC中有一個NSUserDefaults的單例,它可以用來儲存使用者的喜好設定,例如:使用者名稱,字型的大小,使用者的一些設定等,下面我用兩個UISwitch來示範如何儲存使用者佈建開關的關閉狀態
儲存使用者喜好設定
// 擷取使用者喜好設定對象NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];// 儲存使用者喜好設定[defaults setBool:self.one.isOn forKey:@"one"];[defaults setBool:self.two.isOn forKey:@"two"];// 注意:UserDefaults設定資料時,不是立即寫入,而是根據時間戳記定時地把緩衝中的資料寫入本地磁碟。所以調用了set方法之後資料有可能還沒有寫入磁碟應用程式就終止了。// 出現以上問題,可以通過調用synchornize方法強制寫入// 現在這個版本不用寫也會馬上寫入 不過之前的版本不會[defaults synchronize];
讀取使用者喜好設定
// 讀取使用者喜好設定NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; self.one.on = [defaults boolForKey:@"one"];self.two.on = [defaults boolForKey:@"two"];
NSKeyedArchiver歸檔(NSCoding)
只有遵守了NSCoding協議的類才可以用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔,如果對象是NSString、NSDictionary、NSArray、NSData、NSNumber等類型,可以直接用NSKeyedArchiver歸檔和NSKeyedUnarchiver解檔~
下面我舉的??是歸檔解檔一個Student模型,因此該模型應該遵守NSCoding協議
實現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];// 這個檔案尾碼可以是任意的,只要不與熱門檔案的尾碼重複即可,我喜歡用dataNSString *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開發中本機資料儲存的總結
p2:
ios的機密資料用KeyChain儲存
相關連結:ios KeyChain中儲存資料
ios KeyChain項目中應用到的內容
p3:
相關連結:使用ASIHTTPRequest和ASIDownloadCache實現本機快取
1、設定全域的Cache
在AppDelegate.h中添加一個全域變數
[plain] view plaincopy
- @interface AppDelegate : UIResponder
- {
- ASIDownloadCache *myCache;
- }
- @property (strong, nonatomic) UIWindow *window;
- @property (nonatomic,retain) ASIDownloadCache *myCache;
在AppDelegate.m中的- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中添加如下代碼
[plain] view plaincopy
- //自訂緩衝
- ASIDownloadCache *cache = [[ASIDownloadCache alloc] init];
- self.myCache = cache;
- [cache release];
-
- //設定緩衝路徑
- NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
- NSString *documentDirectory = [paths objectAtIndex:0];
- [self.myCache setStoragePath:[documentDirectory stringByAppendingPathComponent:@"resource"]];
- [self.myCache setDefaultCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
在AppDelegate.m中的dealloc方法中添加如下語句
[plain] view plaincopy
- [myCache release];
到這裡為止,就完成了全域變數的聲明。
2、設定緩衝策略
在實現ASIHTTPRequest請求的地方設定request的儲存方式,代碼如下
[plain] view plaincopy
- NSString *str = @"http://....../getPictureNews.aspx";
- NSURL *url = [NSURL URLWithString:str];
- ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
- //擷取全域變數
- AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
- //設定緩衝方式
- [request setDownloadCache:appDelegate.myCache];
- //設定快取資料儲存策略,這裡採取的是如果無更新或無法連網就讀取快取資料
- [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
- request.delegate = self;
- [request startAsynchronous];
3、清理快取資料
我在這裡採用的是手動清理資料的方式,在適當的地方添加如下代碼,我將清理緩衝放在了應用的設定模組:
[plain] view plaincopy
- AppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
- [appDelegate.myCache clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
這裡清理的是ASICachePermanentlyCacheStoragePolicy這種儲存策略的快取資料,如果更換其他的參數的話,即可清理對應儲存策略的快取資料。(參考:http://zycto.blog.163.com/blog/static/17152400201110221340738/)
iOS資料本地持久化