2

いろいろ調べてみると、やりたいことの断片についての投稿がたくさん見つかりましたが、すべてがうまくいくものはありませんでした。

基本的に、静的 plist ファイルがあります。その内容を変更したくありません。plist ファイルは、plist から読み取られて NSArray に格納される辞書の配列であり、データはテーブルに表示されます。これは完全に機能する簡単な部分です。

私が今やりたいことは、静的 plist 配列から読み取ったオブジェクトのユーザーのお気に入りをお気に入りの NSMutableArray に格納する plist を作成することです。この配列は、ユーザーがお気に入りセクションを選択するたびに表示されるお気に入りテーブルに読み込む必要があります。

概念は本当に単純です。ユーザーが「お気に入りに追加」ボタンを押すと、辞書オブジェクトがお気に入り配列に追加されますが、私の問題はお気に入りの plist が存在するかどうかを適切にチェックしています。存在する場合は、そのデータをお気に入り配列に読み込みます。is が存在しない場合は、空の plist を作成します。これは引き続き favorites 配列に読み込まれますが、空になります。

この特定の状況でどこから始めればよいかわかりません。何かアイデアはありますか? どうもありがとう!

4

1 に答える 1

0

初めて同じことをしようとしたときに、自分でこれに遭遇しました。主な問題は、存在しない 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

初めて実行したときのスクリーンショットの例:最初の実行

連続実行のスクリーンショットの例:その後の処刑

于 2013-04-16T23:05:30.473 に答える