Pregunta

Tengo una clase que he hecho en un producto único y soy capaz de salvar a su estado utilizando un NSKeyedArchiver, pero no puedo hacerme a tirar de su estado de vuelta.

En la función que hace la carga que tengo

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

Con este código, lo que hace volver decodeObjectForKey? Realmente no puede ser otra instancia del lugar de celebración y no se carga en cualquiera de los valores guardados. Antes de que me convertí a un ahorro Singleton y la carga estaba funcionando bien.

¿Fue útil?

Solución

Aquí es donde creo que esto va mal. Usted está familiarizado con NSCoding y típicamente adoptarlo al hacer que su objeto a través codificable encodeWithCoder: y initWithCoder: las anulaciones. ¿Qué va a hacer todo esto más simple es que todavía se puede utilizar NSCoding y NSCoders sin anular esos métodos. Puede codificar el estado del objeto compartido sin que codifica la obejct compartida en sí. Esto evita la incómoda pregunta de decodificar el objeto compartido.

Este es un ejemplo de lo que creo que se podría hacer:

@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

Aquí tenemos un objeto compartido, y utiliza archivos con llave de persistir configuración, pero que no codifican el objeto compartido en sí. Este evitar que incómoda pregunta de decodificación de una segunda instancia de la clase singleton.

Otros consejos

Es necesario hacer la carga en el producto único en sí lo que está pasando aquí es crear la única, se asigna una lval a la Singleton, a continuación crea un nuevo objeto y reasignar el lval a ese nuevo objeto sin modificar el singleton . En otras palabras:

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

Lo que se quiere hacer es tratar con esto en el sharedVenue. Hay un par de maneras que la gente hace únicos, por lo que no pueden estar seguros de lo que está haciendo, pero supongamos sharedVenue actualmente es como la siguiente:

static Venue *gSharedVenue = nil;

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

  return gSharedVenue;
}

Si se asume que es el caso que desee cambiar para cargar el objeto en el respaldo mundial 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;
}

Obviamente se necesita para transmitir de alguna manera la trayectoria real de archivo de objeto archivado.

EDITAR BASADO EN COMENTARIO:

De acuerdo, si está utilizando el singleton basado alloc que necesita para hacer frente a esto en el método init clases:

- (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;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top