-----------------------------------------------------------------------Persistenza
-----------------------------------------------------------------------Dopo aver compilato l'elenco delle cartelle, se chiudiamo l'applicazione e la riapriamo, il contenuto è nuovamente VUOTO.
Per fare in modo di rendere sempre disponibile i dati che abbiamo precedentemente inserito, occorre implementare un qualche meccanismo di persistenza dei dati.
La soluzione che andiamo ad implementare consente di salvare i dati in un file, nella cartella documenti dell'utente e successivamente di rileggerli per popolare l'elenco.
Per salvare i dati, utilizziamo il metodo writeToFile disponibile per diverse classi cocoa, nel nostro caso lo useremo per salvare il contenuto dell' NSMutableArray (dsFolders).
Per leggere i dati e ripopolare l'arai usiamo il metodo arrayWithContentsOfFile disponibile per l'oggetto NSMutableArray.
Creo quindi due nuovi metodi della classe FGController, per svolgere questo compito
#pragma mark Salve e Load methods
-(void) saveFoldersList{
NSString* docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
[dsFolders writeToFile:[NSString stringWithFormat:@"%@/FGFolderSize.plist",docDir] atomically:YES];
}
-(void) loadFolderList{
NSString* docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
dsFolders=[NSMutableArray arrayWithContentsOfFile:[NSString stringWithFormat:@"%@/FGFolderSize.plist",docDir]];
[self.tblFoldes reloadData];
}
mettiamo nel file FGController.h le dichiarazioni dei nuovi metodi appena creati.
-(void) saveFoldersList; //Salva l'elenco delle cartelle selezionate
-(void) loadFolderList; //Carica l'elenco delle cartelle selezionate
NOTA
Per memorizzare il file nella cartella Documenti dell'utente, utilizzo la seguente modalità
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
Tramite la funzione NSSearchPathForDirectoriesInDomains, è possibile chiedere al sistema i percorsi delle cartelle standard (es. Documenti, Libreria, Immagini ecc.).
Per comporre il nome del file, occorre indicare tutto il percorso (path) completo che quindi sarà formato dal percorso della directory documenti ed il nome del file che abbiamo scelto (nel nostro caso
FGFolderSize.plist)
Per combinare le due stringhe ed ottere un unica stringa utilizzo il metodo stringWithFormat della classe NSString. [NSString stringWithFormat:@"%@/FGFolderSize.plist",docDir] tale metodo, sostituisce il
simbolo %@ con il valore della variabile, quindi ottengo docDir = "/Users/francesco/Documents"
e NSString stringWithFormat:@"%@/FGFolderSize.plist",docDir] uguale a "/Users/francesco/Documents/FGFolderSize.plist".
Ora che i due metodi sono implementati, occorre che vengano chiamati in modo automatico dopo il lancio dell'applicazione e prima dell'uscita dalla applicazione.
La classe che si occupa di gestire l'avviamento e la chiusura dell'applicazione è la classe delegata già presente nel nostro progetto la FGAppDelegate.h dove avevamo a suo tempo cambiato il titolo della
finestra principale
il metodo già presente applicationDidFinishLaunching è idoneo alla nostra idea di far caricare l'elenco delle cartelle all'avvio del programma, ci serve un qualcosa di analogo per salvare i dati prima di
uscire dall'applicazione.
Cercando nella documentazione proviamo applicationWillTerminate, perfetto.
Lo andiamo ad implementare
//Prima di chiudere l'applicazione
- (void)applicationWillTerminate:(NSNotification *)aNotification{
}
Ho aggiunto anche dei log per vedere se è vero che una è chiamata quando il programma parte e l'altra prima che il programma si chiuda
#import "FGAppDelegate.h"
@implementation FGAppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
self.titoloFinestra=@"Folder Size Calculation";
NSLog(@"Applicazione partita...");
}
//Prima di chiudere l'applicazione
- (void)applicationWillTerminate:(NSNotification *)aNotification{
NSLog(@"Applicazione in chiusura...");
}
@end
Compilo ed eseguo, e controllo il lob, mi pare tutto ok.
NOTA
Unica cosa strana è che se chiudo la finestra, non si chiude in modo automatico l'applicazione.
Per modificare questo comportamento devo implementare
// Chiudo l'applicazione se l'ultima finestra viene chiusa
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender {
return YES;
}
Bene, ora per poter chiamare i metodi della classe FGController
-(void) saveFoldersList; //Salva l'elenco delle cartelle selezionate
-(void) loadFolderList; //Carica l'elenco delle cartelle selezionate
dalla mia classe FGAppDelegate, devo far conoscere alla oggetto di tipo FGAppDelegate l'oggetto di tipo FGController, per fare ciò creo una proprietà con relativo outlet nella classe FGAppDelegate e la
collegherò nell'interfaccia grafica tra i due oggetti (AppDelegate e Controller).
Implemento il file FGAppDelegate.h creando la proprietà theController
xcode mi dice che non conosce la classe FGConroller, quindi aggiungo la definizione con l'istruzione #import
#import "FGConroller.h"
il file FGAppDelegate.h ora è quindi diventato
Provvedo ad effettuare il collegamento della nuova outlet tramite l'interfaccia grafica,
seleziono App Delegato, click e trascino verso Conroller
La situazione per l'oggetto App Delegate è quindi questa, nell'ispettore dei collegamenti vedo theController collegato con Conroller.
se invece controllo la situazione per l'oggetto Conrollet, vedo che è referenziato da una outlet theController dell'oggetto App Delegate
Ora possiamo procedere con la chiamata dei metodi per salvare e caricare i dati.
Ritorniamo su FGAppDelegare.m ed implementiamo tale funzionalità.
Quando l'applicazione parte, carico i dati
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
self.titoloFinestra=@"Folder Size Calculation";
NSLog(@"Applicazione partita...");
[self.theController loadFolderList]; //Carico l'elenco delle cartelle salvate in precedenza
}
Quando l'applicazione sta per uscire, li salvo
//Prima di chiudere l'applicazione
- (void)applicationWillTerminate:(NSNotification *)aNotification{
NSLog(@"Applicazione in chiusura...");
[self.theController saveFoldersList]; //Salvo l'elenco delle cartelle specificate
}
Prima di salutarci, sistemiamo un paio di cosette nel metodo addItem della FGController, non consento immissione di streghe vuote e dopo che ho aggiunto ripulisco il campo di immissione.
-(IBAction)addItem:(id)sender{
NSLog(@"addItem:");
if([self.txtFolder.stringValue isEqualToString:@""]) //Controllo di non avere il campo vuoto
return;
int nIndex = [self searchItem:self.txtFolder.stringValue]; //Controllo di non aver già inserito la cartella
if(nIndex==-1){
//Aggiungo l'elemento indicato nel campo di immissione nell'array
[dsFolders addObject:self.txtFolder.stringValue];
[self.tblFoldes reloadData]; //Segnala alla tabella che qualcosa è cambiato e riaggiorna il contenuto
}
self.txtFolder.stringValue=@""; //Ripulisco il campo di immissione
}
Ci vediamo alla prossima puntata
Francesco Germinara
Scarica

Persistenza - SofTech di Germinara Francesco