【问题标题】:Reading from a plist and then saving objects to a different plist iOS从 plist 读取,然后将对象保存到不同的 plist iOS
【发布时间】:2012-10-26 18:46:44
【问题描述】:

四处搜索后,我发现了大量关于我想做的点点滴滴的帖子,但没有一个可以一起工作。

基本上我有一个静态 plist 文件。我不想改变它的内容。 plist 文件是从 plist 读取并存储在 NSArray 中的字典数组,数据显示在表格上。这是完整且简单的部分!

我现在想做的是有一个 plist,它将用户对从静态 plist 数组读取的对象的收藏夹存储到收藏夹的 NSMutableArray 中。每当用户选择收藏夹部分时,都需要将该数组读入收藏夹表中

这个概念真的很简单,用户将按下“添加到收藏夹按钮”,字典对象将被添加到收藏夹数组中,但我的问题是正确检查收藏夹 plist 是否存在。如果是,则将该数据读入收藏夹数组。如果 is 不存在,则创建一个空的 plist,它仍然会读入收藏夹数组,但它是空的。

对于这种特殊情况,我不确定从哪里开始,有什么想法吗?非常感谢!

【问题讨论】:

    标签: ios6 nsarray plist


    【解决方案1】:

    我自己也遇到了这个问题,第一次尝试做同样的事情。主要问题是您不能写入不存在的 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
    

    第一次运行的截图示例:

    连续运行的示例截图:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-13
      相关资源
      最近更新 更多