Come salvare un oggetto per poi rileggerlo in seguito

Objective-C

Una funzionalità molto utile è quella di poter creare degli oggetti e poterli salvare su disco.

Ad esempio potremmo avere bisogno di salvare una cache o delle impostazioni molto complesse e poterle riutilizzare in seguito.
Objective-C ci aiuta anche in questo con delle classi molto utili e semplici da utilizzare.

Il concetto di base è semplice, dobbiamo trasformare il nostro oggetto in Dati (NSData) e poi salvarlo. Ma se proviamo a farlo ad un nostro oggetto probabilmente riceveremo qualche errore.

La cosa necessaria infatti è che l’oggetto che vogliamo salvare sia conforme al protocollo NSCoding.

Vediamo come utilizzarlo e come poter permettere il salvataggio e il recupero di questi dati.

Creiamo una classe di esempio, sottoclasse di NSObject e con il nome “SampleObject”. Rendiamola conforme al protocollo NSCoding e dichiariamo tre proprietà:

@interface SampleObject : NSObject 

@property (nonatomic, strong) NSString* name;
@property (nonatomic, strong) NSDate* birthDate;
@property (nonatomic, readwrite) NSInteger age;

@end

A questo punto però dobbiamo implementare i due metodi necessari affinché il protocollo permetta di fare il lavoro in modo corretto.

- (id)initWithCoder:(NSCoder *)aDecoder
{
	if ((self = [super init]))
	{
		_name = [aDecoder decodeObjectForKey:@"name"];
		_birthDate = [aDecoder decodeObjectForKey:@"birthDate"];
		_age = [aDecoder decodeIntegerForKey:@"age"];
	}
	return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
	[aCoder encodeObject:_name forKey:@"name"];
	[aCoder encodeObject:_birthDate forKey:@"birthDate"];
	[aCoder encodeInteger:_age forKey:@"age"];
}

Quello che avviene è la codificazione e la decodificazione delle variabili all’interno dell’oggetto quando NSCoding lo richiede.

In particolare c’è metodo di inizializzazione e uno che viene richiamato nel momento in cui cercheremo di codificare l’oggetto.

Adesso torniamo al nostro ViewController ed andiamo ad inizializzare il nostro oggetto. Assegnamo le proprietà:

SampleObject* object = [SampleObject new];
object.name = @"Andrea";
object.birthDate = [NSDate date];
object.age = 28;

A questo punto l’oggetto è completamente funzionante infatti possiamo farci stampare dal debugger i suoi dati:

Object name Andrea, birthDate 2014-10-29 16:43:26 +0000, age 28

Ora proviamo a salvarlo in NSUserDefaults.
Ciò che dobbiamo fare quindi è trasformarlo in NSData e per fare questi ci viene in aiuto la classe NSKeyedArchiver:

NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults];
NSData* dataObject = [NSKeyedArchiver archivedDataWithRootObject:object];
	
[userDefaults setObject:dataObject forKey:@"object"];
[userDefaults synchronize];

Adesso è quindi salvato all’interno di NSUserDefault dell’utente.
Possiamo ricrearlo quando vogliamo ed anche qui ci facciamo aiutare da un altra classe di Objective-C chiamata NSKeyedUnarchiver:

NSData* restoredDataObject = [userDefaults objectForKey:@"object"];
SampleObject* restoredObject = [NSKeyedUnarchiver unarchiveObjectWithData:restoredDataObject];

Et-Voilà, ecco il nostro oggetto esattamente come prima e il debugger sarà felice di dirci quali sono i suoi dati:

restoredObject name Andrea, birthDate 2014-10-29 16:43:26 +0000, age 28

La procedura è un po’ macchinosa e non rimane facilmente in mente, per non parlare di quando l’oggetto è complesso.. risulterà sicuramente noiosa ma le potenzialità sono infinite.

Scritto il