NSKeyedArchiverからシングルトンの状態をロード
-
18-09-2019 - |
質問
私はシングルトンに作られ、それがNSKeyedArchiverを使用して状態だが、私はそれが戻って状態だ引っ張っまわりで私の頭をラップすることはできません保存することができていましたクラスを持っています。
私はロードを行う機能で
Venue *venue = [Venue sharedVenue];
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
venue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];
このコードでは、decodeObjectForKeyは何を返すのでしょうか?それは本当に会場の別のインスタンスにすることはできず、それが保存された値のいずれかにロードしていません。私は保存と読み込みがうまく働いていたシングルトンにそれを変換する前に。
解決
ここにあります。あなたはNSCodingに精通していると一般的にencodeWithCoderを経由して、あなたのオブジェクトコード可能なを作ることによって、それを採用:とinitWithCoder:上書き。これは、すべて簡単になりますと、あなたはまだ、これらのメソッドをオーバーライドすることなく、NSCoding、およびNSCodersを使用することができるということです。あなたは共有obejct自体をコードすることなく、共有オブジェクトの状態をエンコードすることができます。これは、共有オブジェクトをデコードするの厄介な問題を防止します。
ここで私はあなたができると思うものの例です。
@implementation MySharedObject
+ (id)sharedInstance {
static id sharedInstance = nil;
if (!sharedInstance) {
sharedInstance = [[MyClass alloc] init];
}
}
- (id)init {
if ((self = [super init])) {
NSData *data = /* probably from user defaults */
if (data) { // Might not have any initial state.
NSKeyedUnarchiver *coder = [[[NSKeyedUnarchiver alloc] initForReadingWithData:data] autorelease];
myBoolean = [coder decodeBoolForKey:@"MyBoolean"];
myObject = [[coder decodeObjectForKey:@"MyObject"] retain];
[coder finishDecoding];
}
}
return self;
}
- (void)saveState {
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *coder = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
[coder encodeBool:myBoolean forKey:@"MyBoolean"];
[coder encodeObject:myObject forKey:@"MyObject"];
[coder finishEncoding]
// Save the data somewhere, probably user defaults...
}
@end
ここでは、共有オブジェクトを持って、それが設定を永続化するキー付きアーカイブを使用していますが、我々は共有オブジェクト自体をコードしません。これはシングルトンクラスの2番目のインスタンスを復号化すること厄介な問題を回避します。
他のヒント
あなたはここで何が起こっているかシングルトン自体に読み込みを行う必要があるあなたは、単一の作成で、あなたはシングルトンにLVALを割り当て、あなたはその後、シングルトンを変更せずに新しいオブジェクトを作成し、その新しいオブジェクトにLVALを再割り当て。つまります:
//Set venue to point to singleton
Venue *venue = [Venue sharedVenue];
//Set venue2 to point to singleton
Venue *venue2 = [Venue sharedVenue];
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
//Set venue to unarchived object (does not change the singleton or venue2)
venue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];
やりたいことsharedVenueでこれに対処です。そこの人々はシングルトンを行ういくつかの方法があるので、私はあなたが何をしているか確認することはできませんが、sharedVenueは現在、次のようになりますと仮定することができます:
static Venue *gSharedVenue = nil;
- (Venue *) sharedVenue {
if (!gSharedVenue) {
gSharedVenue = [[Venue alloc] init];
}
return gSharedVenue;
}
それはあなたが世界の裏にシングルトンをオブジェクトをロードするために、それを変更したい場合であると仮定します:
static Venue *gSharedVenue = nil;
- (Venue *) sharedVenue {
if (!gSharedVenue) {
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[data release];
gSharedVenue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];
[unarchiver release];
}
if (!gSharedVenue) {
gSharedVenue = [[Venue alloc] init];
}
return gSharedVenue;
}
もちろん、あなたが何らかの形でアーカイブされたオブジェクト・ファイルへの実際のパスを伝える必要があります。
COMMENTに基づくEDITます:
さて、あなたはクラスのinitメソッドでこれに対処する必要があるのallocベースのシングルトンを使用している場合:
- (id) init {
self = [super init];
if (self) {
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[data release];
Venue *storedVenue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];
[unarchiver release];
if (storeVenue) {
[self release];
self = [storedVenue retain];
}
}
return self;
}