天天看點

【轉】plist涉及到沙盒的一個問題

儲存玩家資料,模拟器讀寫都可以,而真機plist檔案隻能讀不能寫,十分頭大,弄球一天找到了問題所在。

按照網上比較有說服力的說法是:iOS程式執行的時候是在“沙盒”裡執行。而沙盒裡的資料不能寫入,隻能讀取。

經過測試,當一個程式在執行的時候,比如叫 Test.app 的iOS程式,獲得他的執行位址的代碼是(比如找的是CFG.plist檔案)

NSBundle *bundle = [ NSBundle mainBundle ];

NSString *filePath = [ bundle pathForResource:@"CFG" ofType:@"plist" ];

filePath列印出來的執行位址應該類似

Support/iPhone Simulator/5.0/Applications/3B5DBF75-18D2-43EA-B26F-7FEDECAFDC92/Test.app/CFG.plist

每 個應用程式都一個固定且唯一的ID(上面的3B5DBF75-18D2-43EA-B26F-7FEDECAFDC92),這個ID被作為iOS執行時的 一個用來修飾的檔案夾,這樣可以保證每個應用都是獨立的,哪怕名字一樣。而這個ID檔案夾下有一系列實際存在的檔案夾。而Test.app隻是其中一個, 裡面有實際的遊戲資料。如果要想儲存資料,那麼應該将資料寫入到一個叫做“Documents”的檔案夾下。通路路徑的代碼如下:

 NSArray *doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docPath = [ doc objectAtIndex:0 ];

執行結果是 Support/iPhone Simulator/5.0/Applications/3B5DBF75-18D2-43EA-B26F-7FEDECAFDC92/Documents

可以看到系統檔案名ID和上面的一樣。

綜 上所述。當有資料為隻讀的時候,應該放到app應用裡的plist裡,當資料要做修改,應該放到documents裡。比如遊戲裡的物品資料,這種不能被 修改的放到app裡,而玩家的合成裝備應該在documents裡手動建立一個plist來存儲。那麼首要問題就是要判斷,documents裡是否已有 資料。

NSArray *doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *docPath = [ doc objectAtIndex:0 ];

if( [[NSFileManager defaultManager] fileExistsAtPath:[docPathstringByAppendingPathComponent:@"Score.plist"] ]==NO ) {

   // ============================== 寫入plist初始化資料(最後有,先說讀取)

}

讀取:

NSArray *doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *docPath = [ doc objectAtIndex:0 ]; // 字典集合。  

NSDictionary *dic = [ NSDictionary dictionaryWithContentsOfFile:[docPathstringByAppendingPathComponent:@"Score.plist"] ]; // 解析資料

NSString *content = [ dic objectForKey:@"Score" ];

NSArray *array = [ content componentsSeparatedByString:@","];

content裡就是“Score”裡所存儲的資料,array是将content裡的資料按“,”拆分,僅将兩個“,”之間的資料儲存。

寫入:一定要注意,必須建立一個新的NSMutableDictionary

// 用來覆寫原始資料的新dic

NSMutableDictionary *newDic = [ [ NSMutableDictionary alloc ] init ];

// 新資料

NSString *newScore = @"100,200,300";

// 将新的dic裡的“Score”項裡的資料寫為“newScore”

[ newDic setValue:newScore forKey:@"Score" ];

// 将 newDic 儲存至docPath+“Score.plist”檔案裡,也就是覆寫原來的檔案

NSArray *doc = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

NSString *docPath = [ doc objectAtIndex:0 ];

[ newDic writeToFile:[docPath stringByAppendingPathComponent:@"Score.plist"] atomically:YES ];