剛剛碰到這個自己,同時嘗試第一次做同樣的事情。主要問題是你不能寫信給不存在的plist。所以你需要在你的軟件包中創建一個,並將其複製到你需要的位置,「如果它不存在」。這是一個例子。這比「最小」多一點,但我認爲它解釋了這些問題。其結果是通過將某些內容存儲在文檔目錄中某處的「data.plist」中,從一次運行轉移到另一次運行。
在ViewController.m
(例如):
#import "ViewController.h"
@interface ViewController()
@end
@implementation ViewController
////////////////////////////
// BIG NOTE:
// In order for ANY of this to work, you need to make a data.plist in your supporting files, in your project,
// before compiling and running
// The plist should, at very least, have a single row with key "key1" and value "value1"
////////////////////////////
// returns path where plist file is
// "internal" means whether we want from one baked into the app (which is read-only, by the way), or one in our documents dir
-(NSString *)localPathForPlist:(NSString *)name internal:(bool)internal
{
if(internal) return [[NSBundle mainBundle] pathForResource:name ofType:@"plist"];
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
return [documentsDirectory
// this just adds name and ".plist" to make a filename something like "data.plist"
stringByAppendingPathComponent:[NSString stringWithFormat:@"%@%@", name, @".plist"]
];
}
// write value to key, either in internal plist or not
-(void) writeToPlist:(NSString *)key setValue:(NSString *)value internal:(bool)internal
{
NSString* path = [ self localPathForPlist:@"data" internal:internal ];
NSMutableDictionary *plistData = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[plistData setObject:value forKey:key];
[plistData writeToFile:path atomically:YES];
}
// read value from key, either in internal plist or not
-(NSString *) readFromPlist:(NSString *)key internal:(bool)internal
{
NSString* path = [ self localPathForPlist:@"data" internal:internal ];
NSMutableDictionary *plistData = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
return (NSString *)[plistData valueForKey:key];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// here we go through all the different cases, trying to edit things internally and in externally,
// and copying the internal one to the external location, towards the end, if it's not already there
NSString *localPath = [self localPathForPlist:@"data" internal:FALSE];
NSString *internalPath = [self localPathForPlist:@"data" internal:TRUE];
NSLog(@"local path=%@", localPath);
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL localPlistExists = [fileManager fileExistsAtPath:localPath];
// the first time you run this, it'll do one, then the other for all other runs:
if(localPlistExists) NSLog(@"local plist exists");
else NSLog(@"local plist does NOT exist");
NSLog(@"key1's value from internal=%@", [self readFromPlist:@"key1" internal:TRUE ]);
NSLog(@"key1's value from external=%@", [self readFromPlist:@"key1" internal:FALSE]);
NSLog(@"setting internal key1 to new-value1");
[self writeToPlist:@"key1" setValue:@"new-value1" internal:TRUE ];
NSLog(@"setting external key1 to new-value1");
[self writeToPlist:@"key1" setValue:@"new-value1" internal:FALSE];
NSLog(@"key1's value from internal=%@", [self readFromPlist:@"key1" internal:TRUE ]);
NSLog(@"key1's value from external=%@", [self readFromPlist:@"key1" internal:FALSE]);
// the first time you run this, it'll do one, then the other for all other runs:
if(localPlistExists) NSLog(@"since local plist exists, leaving alone");
else
{
NSLog(@"since local plist does NOT exist, cloning from internal copy");
[fileManager copyItemAtPath:internalPath toPath:localPath error:nil];
}
NSLog(@"key1's value from internal=%@", [self readFromPlist:@"key1" internal:TRUE ]);
NSLog(@"key1's value from external=%@", [self readFromPlist:@"key1" internal:FALSE]);
NSLog(@"setting internal key1 to new-value1");
[self writeToPlist:@"key1" setValue:@"new-value1" internal:TRUE ];
NSLog(@"setting external key1 to new-value1");
[self writeToPlist:@"key1" setValue:@"new-value1" internal:FALSE];
NSLog(@"key1's value from internal=%@", [self readFromPlist:@"key1" internal:TRUE ]);
NSLog(@"key1's value from external=%@", [self readFromPlist:@"key1" internal:FALSE]);
// notice that from one run to another, changes to the internal one don't "carry over", because it's read-only
// but ones in the external one do
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
實施例的屏幕截圖的第一次運行它:
實施例的屏幕截圖爲連續運行: