2012-04-11 176 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