0

Web サービスからのデータを初期化し、それ自体を (NSCoding と NSKeyedUnarchiver を使用して) ファイルに保存するシングルトン クラスがあるので、Web からすべてのデータを再度取得する代わりに、このファイルを初期化することができます。保存されているのはシングルトン インスタンスであるため、通常のようにシングルトン ゲッターを呼び出し、アーカイブされたコピーがあるかどうかを確認し、そうでない場合はデータをプルダウンしてアーカイブできるようにしたいと考えています。アーカイブは正常に機能していますが、[[NSKeyedUnarchiver unarchiveObjectWithFile: filePath] preserve] を呼び出そうとすると、sharedInstance が初期化される前に sharedInstance ゲッターが呼び出されます。これにより init が呼び出され、アプリはすべてのデータを再度ダウンロードしますが、その後 unarchiver によって上書きされます。

セットアップに何か問題がありますか、またはこのデータをシリアル化する別の方法はありますか?

ここにいくつかの(簡略化された)コードがあります:

@implementation Helmets
@synthesize helmetList, helmetListVersion;
//Class Fields
static Helmets *sharedInstance = nil;

// Get the shared instance and create it if necessary.
+ (Helmets *)sharedInstance {
    //if(sharedInstance == nil){
        //[Helmets unarchive];             //This does not work! Calls sharedInstance() again (recursion)
        if(sharedInstance == nil){
            sharedInstance = [[super allocWithZone:NULL] init];    //Pull from web service
            [Helmets archive];    //Save instance
        //}
    //}
    return sharedInstance;
}

- (id)init {
    self = [super init];
    if (self) {
            helmetList = [[NSMutableArray alloc]init];

            //Get our data from the web service and save it (excluded)
            }
    }
    return self;
}

//This works!
+(void)archive{
    if([NSKeyedArchiver archiveRootObject:sharedInstance toFile:[Helmets getFilePath]]){
        NSLog(@"Archiving Successful");
    }
    else{
        NSLog(@"Archiving Failed");
    }
}

//This works, but calls getInstance causing data to be downloaded anyways!
+(void)unarchive{
    // Check if the file already exists
    NSFileManager *filemgr = [NSFileManager defaultManager];
    NSString *filePath = [Helmets getFilePath];
    if ([filemgr fileExistsAtPath: filePath])
    {
       sharedInstance = [[NSKeyedUnarchiver unarchiveObjectWithFile: filePath] retain];
    }
    [filemgr release];
}

インスタンスは次のように初期化されます。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions{
    ...
    [Helmets unarchive];        //This calls sharedInstance() too soon!
    [Helmets sharedInstance];
}

このクラスは .h に NSCoding を実装し、initWithCoder と encodeWithCoder をオーバーライドします (アーカイブは機能しています)。

前もって感謝します!

4

2 に答える 2

2

最終的には、所有しているインスタンスに加えて共有インスタンスを設定するためのプライベート メソッドが必要であり、別の init が必要であり、これも実装に対してプライベートです。

- (id)initAndFetch:(BOOL)fetch
{
    if((self = [super init])) {
        ...

        if(fetch) { do the web fetch };
             ...   
    }
}

+sharedInstance メソッドでは、YES を渡します。

次に、デコードは次のようになります。

- (id)initWithCoder:(NSCoder *)decoder
{
    if((self = [self initAndFetch:NO])) {
        title = [decoder decodeObjectForKey:@"title"];
        ...
        sharedInstance = self;
    }
    return self;
}
于 2012-08-29T21:19:02.877 に答える