Frage

Ich habe eine Klasse, die ich in eine Singleton gemacht habe und bin in der Lage, es ist Zustand mit einem NSKeyedArchiver zu speichern, aber ich kann meinen Kopf nicht umschlingen zieht es Zustand ist wieder aus.

In der Funktion, die das Laden funktioniert Ich habe

Venue *venue = [Venue sharedVenue];
NSData *data = [[NSMutableData alloc] initWithContentsOfFile:[self dataFilePath]];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
venue = [unarchiver decodeObjectForKey:@"Venue"];
[unarchiver finishDecoding];

Mit diesem Code, was bedeutet decodeObjectForKey zurückkehren? Es kann nicht wirklich eine andere Instanz Veranstaltungsort sein und es ist nicht in einem der gespeicherten Werte zu laden. Bevor ich es auf eine Singleton Spar umgewandelt und Laden war gut funktioniert.

War es hilfreich?

Lösung

Hier ist, wo ich denke, das ist nicht in Ordnung ist. Sie sind mit NSCoding vertraut und die Annahme es in der Regel von Ihrem Objekt codierbarem über encodeWithCoder machen: und initWithCoder: Überschreibungen. Was macht all dies einfacher ist, dass man immer noch NSCoding und NSCoders ohne zwingende diese Methoden verwenden kann. Sie können ohne Codierung des gemeinsamen obejct selbst den Zustand des gemeinsam genutzten Objekts kodieren. Dies verhindert, dass die peinliche Frage das gemeinsame Objekt der Decodierung.

Hier ist ein Beispiel dafür, was ich denken konnte, was Sie tun:

@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

Wir haben hier ein gemeinsames Objekt, und es verwendet Schlüsselarchivkonfiguration zu bestehen, aber wir kodieren nicht das gemeinsame Objekt selbst. Dies vermeiden, dass die heikle Frage, eine zweite Instanz des Singleton-Klasse der Decodierung.

Andere Tipps

Sie müssen die Belastung in der Singleton selbst tun, was hier los ist Sie die Einzel erstellen, erhalten Sie eine lval zum Singleton zuzuweisen, geben Sie dann ein neues Objekt erstellen und die lval zu diesem neuen Objekt zuweisen, ohne die Singleton zu Modifizieren . Mit anderen Worten:

//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];

Was Sie tun möchten, ist Deal mit diesem in der sharedVenue. Es gibt ein paar Möglichkeiten, die Menschen Singletons tun, so kann ich nicht sicher sein, was Sie tun, aber lässt vermuten, sharedVenue derzeit etwa wie folgt aussieht:

static Venue *gSharedVenue = nil;

- (Venue *) sharedVenue {
  if (!gSharedVenue) {
    gSharedVenue = [[Venue alloc] init];
  }

  return gSharedVenue;
}

Unter der Annahme, dass der Fall, dass Sie es ändern möchten, das Objekt in die globale Unterstützung der Singleton zu laden:

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;
}

Natürlich müssen Sie irgendwie den tatsächlichen Pfad zu archivierten Objektdatei übermitteln.

EDIT BASED ON KOMMENTAR:

Okay, wenn Sie mit dem alloc basierend Singletons Sie müssen mit dieser in den Klassen init-Methode behandeln:

- (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;
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top