2012-04-11 243 views
0

我目前需要讀取和寫入plist文件。 這是我目前的狀態: 我創建了一個名爲「Scores.plist」的plist文件,我已將它放在我的xcode項目的Resources文件夾中。在plist文件中包含一個帶有「Score」鍵的字典。附加到密鑰的對象是一個佔位符值爲1010的NSNumber。 當我運行我的代碼時,我得到了奇怪的結果。 我的plist位於錯誤的地方嗎? 我聽說plist應該位於一些文檔目錄中,用於閱讀和書寫。但是,我不確定這是什麼,確切地說。 任何幫助表示讚賞。提前致謝! :)從plist文件中寫入和讀取

-(void)writeToPlistHighScore:(int)scoreNumber { 
    //attempt to write to plist 
    //however both the nslog's in this first section result in "null" 
    NSString *documentsDirectory = [NSSearchPathForDirectoriesInDomains(NSLibraryDirectory, NSUserDomainMask, YES) objectAtIndex:0]; 
    NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"Scores.plist"]; 

//NSString *scorePath2 = [[NSBundle mainBundle] pathForResource:@"Scores" ofType:@"plist"]; 
NSDictionary *plistDict = [[NSDictionary dictionaryWithContentsOfFile:filePath] retain]; 
NSLog(@"%@",[plistDict objectForKey:@"Score"]); 
[plistDict setObject:[NSNumber numberWithInt:scoreNumber] forKey:@"Score"]; 
[plistDict writeToFile:filePath atomically: YES]; 
NSLog(@"%@",[plistDict objectForKey:@"Score"]); 
[plistDict release]; 

//Stable code for reading out dictionary data 
//this code reads out the dummy variable in Scores.plist located in my resources folder. 
// Path to the plist (in the application bundle) 
NSString *scorePath = [[NSBundle mainBundle] pathForResource:@"Scores" ofType:@"plist"]; 
NSDictionary *plistData = [[NSDictionary dictionaryWithContentsOfFile:scorePath] retain]; 
NSString *scoreString = [NSString stringWithFormat:@"Score:%@", [plistData objectForKey:@"Score"]]; 
NSLog(@"%@",scoreString); 

//checking to see where my file is... 
//this logs a file path which I don't know means 
NSError *error; 
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 
NSString *documentsDirectory2 = [paths objectAtIndex:0]; 
NSString *path = [documentsDirectory2 stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist",@"Scores"]]; 

NSFileManager *fileManager = [NSFileManager defaultManager]; 

if (![fileManager fileExistsAtPath: path]){ 
    NSLog(@"File don't exists at path %@", path); 

    NSString *plistPathBundle = [[NSBundle mainBundle] pathForResource:@"Scores" ofType:@"plist"]; 

    [fileManager copyItemAtPath:plistPathBundle toPath: path error:&error]; 
}else{ 
    NSLog(@"File exists at path:%@", path); 
} 

}

回答

1

簡短的回答是,你要使用NSDocumentDirectory而不是NSLibraryDirectory。

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

要保存到應用程序的文件目錄的沙箱中,而不是它的應用程序包。您不允許在運行時更改應用程序包中的任何內容。

請參閱http://developer.apple.com/library/mac/#documentation/FileManagement/Conceptual/FileSystemProgrammingGUide/FileSystemOverview/FileSystemOverview.html瞭解詳細說明。

現在的技巧是,如果你想加載一個默認的plist文件,如果還沒有保存呢?那麼,首先檢查你的文檔目錄,如果沒有文件保存在那裏,然後從你的資源目錄加載一個模板。更好的是,如果它看起來像一個簡單的結構,只需在代碼中創建NSDictionary,然後使用writeToFile:atomically:將其保存爲plist格式。

http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/PropertyLists/QuickStartPlist/QuickStartPlist.html#//apple_ref/doc/uid/10000048i-CH4-SW5有一個很好的解釋plist處理。它使用Mac OS X應用程序作爲示例,但概念可轉移到iOS。

順便說一句,你正在採取一些不必要的步驟與您的保留和發佈。 dictionaryWithContentsOfFile創建一個自動釋放對象,所以不需要保留它,因此在完成時不需要釋放它。你可以做到你在你的代碼第1塊內做同樣的事情:

NSDictionary *plistDict = [NSDictionary dictionaryWithContentsOfFile:filePath]; 
NSLog(@"%@",[plistDict objectForKey:@"Score"]); 
[plistDict setObject:[NSNumber numberWithInt:scoreNumber] forKey:@"Score"]; 
[plistDict writeToFile:filePath atomically: YES]; 
NSLog(@"%@",[plistDict objectForKey:@"Score"]); 

plistDict將自動釋放當前的運行循環迭代時。我提到這一點是因爲你在你的示例中未能釋放plistData,如果稍後沒有發佈,這是內存泄漏,而你可以通過不保留plistData來避免這種情況。有關自動釋放對象的詳細說明,請參閱https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-CJBFBEDI