Domanda

Ho una classe che ho fatto in un Singleton e sono in grado di salvare suo stato utilizzando un NSKeyedArchiver, ma non posso avvolgere la mia testa intorno tirando suo stato di nuovo fuori.

Nella funzione che fa il carico che ho

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

Con questo codice, che cosa decodeObjectForKey tornare? Non può essere in realtà un altro esempio di sede e non è di caricare in uno qualsiasi dei valori salvati. Prima ho convertito a un risparmio Singleton e di carico di lavoro andava bene.

È stato utile?

Soluzione

Ecco dove credo che questo sta andando male. Si ha familiarità con NSCoding e in genere l'adozione di esso, rendendo il vostro codificabile oggetto tramite encodeWithCoder: e initWithCoder: sostituzioni. Che cosa farà questo tutto più semplice è che si può ancora utilizzare NSCoding, e NSCoders senza sostituire quei metodi. È possibile codificare lo stato dell'oggetto condiviso, senza che codifica per l'obejct condivisa in sé. Questo impedisce la domanda scomoda di decodificare dell'oggetto condiviso.

Ecco un esempio di quello che penso che si possa fare:

@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

Qui abbiamo un oggetto condiviso, e utilizza archivio con chiave a persistere la configurazione, ma non codificare l'oggetto condiviso in sé. Ciò evita che domanda scomoda di decodifica di una seconda istanza della classe singleton.

Altri suggerimenti

Hai bisogno di fare il carico nella Singleton per sé quello che sta succedendo qui è di creare il singolo, si assegna un lval al Singleton, quindi si crea un nuovo oggetto e riassegnare il lval a quel nuovo oggetto senza modificare il singleton . In altre parole:

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

Che cosa si vuole fare è affrontare questo nel sharedVenue. Ci sono un paio di modi le persone fanno single, quindi non posso essere sicuro di quello che state facendo, ma lascia supporre sharedVenue attualmente simile a questa:

static Venue *gSharedVenue = nil;

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

  return gSharedVenue;
}

Supponendo che è il caso che si desidera modificare per caricare l'oggetto nel supporto globale Singleton:

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

Ovviamente è necessario trasmettere in qualche modo il percorso effettivo al file oggetto archiviato.

EDIT BASATI SU COMMENTO:

Va bene, se si utilizza il Singleton basato alloc è necessario affrontare questo nel metodo init classi:

- (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;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top