1

私は iPad と iPod 用のクックブック アプリケーションを作成しており、クックブック クラスにレシピ クラスの配列があります。

@interface Cookbook : NSObject<NSCoding>{
NSMutableArray* recipes;
}

それは私のCookbookクラスにあり、私のレシピクラスにはこれがあります:

@interface Recipe : NSObject<NSCoding>{
NSString* name;
NSMutableArray* ingredients; //List of ingredients for the recipe
UIImage* recipePicture;
NSMutableArray* instructions;
unsigned int prepTime;//in seconds
NSDate* dateAdded;
}

(実際にはここにもっと変数がありますが、これを過剰な量でフラッディングしたくありませんでした)

私の問題は基本的に保存/読み込み機能にあります。ここで以前に同様の質問をしたことがあります: プロパティ リスト オブジェクトではない Objective-C オブジェクトを保存するにはどうすればよいですか、またはプロパティ リストよりも良い方法はありますか?

これにより、NSCoding を使用するのが最善であると判断し、NSCoding で提案された方法に従って、そのためのメソッドも既に実装しています。

私の主な問題は、レシピを保存して正常に取得できないことです。

また、レシピを保存する RecipeList.plist ファイルへのディレクトリを取得するのにも問題がありました。

これが私がこのアプリケーションを作成し続けることができない理由であるため、どんな助けも大歓迎です.

私のCookbook.mには次のものがあります:

-(id) initWithCoder:(NSCoder *)aDecoder{
NSLog(@"Init With Coder - Cookbook");
if(self = [super init]){
    recipes = [aDecoder decodeObjectForKey:@"recipes"];
}
return self;
}

私の Recipe.m では:

-(id) initWithCoder:(NSCoder *)aDecoder{
if(self = [super init]){
    name = [aDecoder decodeObjectForKey:@"name"];
    ingredients = [aDecoder decodeObjectForKey:@"ingreds"];
    recipePicture = [aDecoder decodeObjectForKey:@"recipePict"];
}
return self;
}

繰り返しますが、そこにはさらに多くの変数があります。これは単純にするためです。また、これは RecipeList.plist へのファイル パスを取得する私の試みです。

+(NSString*) filePath{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,     NSUserDomainMask, YES);
NSString *path = [paths objectAtIndex:0];
path = [path stringByAppendingPathComponent:@"RecipeList.plist"];

NSLog(@"%@",path);
return path;
}

私の AppDelegate.m での save メソッドの試み:

-(void) save:(NSString *)path cookbook:(Cookbook *)cookbook{
BOOL b = [[NSFileManager defaultManager] fileExistsAtPath:path];
NSLog(@"File exists: %i",b); //1 = exists, 0 = doesn't

NSMutableData* data = [[NSMutableData alloc] init];
if(data){ //If the data object was successfully initialized
    NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
    if(archiver){
        //Encode the recipe using the coder method defined in recipe.
        [archiver encodeInt:1 forKey:@"Version"];
        [archiver encodeObject:cookbook forKey:@"Cookbook"];
        [archiver finishEncoding];

        [data writeToFile:path atomically:YES];
    }
}
}

そして私のロード方法:

-(Cookbook *) loadCookbook:(NSString *)path{
BOOL b = [[NSFileManager defaultManager] fileExistsAtPath:path];
NSLog(@"File exists: %i",b);

Cookbook* ret = nil;
NSData* data = [NSData dataWithContentsOfFile:path];
if(data){
    NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
    int version = [unarchiver decodeIntForKey:@"Version"];
    if(version == 1){
        ret = (Cookbook*) [unarchiver decodeObjectForKey:@"Cookbook"];
    }
    [unarchiver finishDecoding];
}
return ret;
}

これと非常によく似た Recipe クラスの保存および読み込みメソッドもあります。

繰り返しになりますが、お役に立てば幸いです。時間を割いて読んでいただきありがとうございます。

編集: これは、簡潔にするためにいくつかの変数を省略した Recipe.m の encodeWithCoder メソッドです。

-(void) encodeWithCoder:(NSCoder *)aCoder{
NSLog(@"Encoding Recipe.");
[aCoder encodeObject:name forKey:@"name"];
[aCoder encodeObject:ingredients forKey:@"ingreds"];
[aCoder encodeObject:recipePicture forKey:@"recipePict"];
[aCoder encodeObject:instructions forKey:@"instructs"];
[aCoder encodeObject:category forKey:@"categ"];
[aCoder encodeObject:dateAdded forKey:@"dateAdd"];
[aCoder encodeInt:prepTime forKey:@"prepTime"];

}

そしてCookbook.mで:

-(void) encodeWithCoder:(NSCoder *)aCoder{
NSLog(@"Encoding cookbook.");
[aCoder encodeObject:recipes forKey:@"recipes"];
}
4

1 に答える 1

0

私はあなたのコードを「ほとんど」コピーして貼り付けました。いくつかの小さな調整の後、私はそれを稼働させました。

クックブックに以下を追加しました。

- (id)init {
    if (self = [super init]) {
        recipes = [NSMutableArray array];
    }
    return self;
}

- (void)addRecipe:(Recipe *)recipe {
    [recipes addObject:recipe];
}

あなたはすでにそれらを持っているかもしれませんか?どこかで配列をインスタンス化していると思いますか?

次に、このテストルーチンを使用して、クックブックが作成、使用、保存されます。

NSString *path = [self filePath];
Cookbook *cookbook = [self loadCookbook:path];

if (cookbook) {
    NSLog(@"Loaded cookbook: %@", cookbook);
}
else {
    cookbook = [[Cookbook alloc] init];
}

Recipe *recipe = [[Recipe alloc] init];
recipe->name = @"The name";
[cookbook addRecipe:recipe];

[self save:path cookbook:cookbook];
NSLog(@"Saved cookbook: %@", cookbook);

fyi : 簡潔にするために、レシピのインスタンス変数を @public にしました。うまくいけば、アクセサー (@property) を使用しています。

自動参照カウントと手動参照カウントのどちらを使用していますか?

于 2012-12-21T09:19:28.957 に答える