I dati persistenti attraverso i lanci di applicazioni sono un requisito che la maggior parte delle applicazioni iOS ha, dalla memorizzazione delle preferenze dell'utente utilizzando il sistema di default dell'utente alla gestione di grandi set di dati in un database relazionale. In questo articolo, esploreremo le strategie più comuni utilizzate per la memorizzazione dei dati in un'applicazione iOS. Parlerò anche del file system su iOS e del modo in cui il sandboxing delle applicazioni influisce sulla persistenza dei dati.
Hai fatto molta strada, cavalletta, e hai imparato molto. Tuttavia, c'è un aspetto vitale dello sviluppo di iOS che non abbiamo ancora discusso, la persistenza dei dati. Praticamente ogni applicazione iOS memorizza i dati per un uso successivo. I dati memorizzati dall'applicazione iOS possono essere qualsiasi cosa, dalle preferenze dell'utente alle cache temporanee o persino a grandi set di dati relazionali.
Prima di discutere le più comuni strategie di persistenza dei dati che gli sviluppatori hanno sulla piattaforma iOS, passerò alcuni minuti a discutere del file system e del concetto di sandboxing dell'applicazione. Pensavi davvero di poter archiviare i dati della tua applicazione ovunque ti trovassi sul file system? Pensa di nuovo, padawan.
La sicurezza sulla piattaforma iOS è stata una delle massime priorità di Apple da quando l'iPhone è stato introdotto nel 2007. Contrariamente alle applicazioni OS X, un'applicazione iOS è collocata in una sandbox dell'applicazione. Contrariamente a quanto molti pensano, la sandbox di un'applicazione non si riferisce solo alla directory sandbox di un'applicazione nel file system. La sandbox dell'applicazione include anche l'accesso controllato e limitato ai dati utente memorizzati sul dispositivo, i servizi di sistema e l'hardware.
Con l'introduzione del Mac App Store, Apple ha iniziato a imporre l'applicazione sandboxing anche su OS X. Anche se i limiti imposti alle applicazioni OS X non sono così rigidi come quelli imposti sulle applicazioni iOS, il concetto generale è simile ma non identico. La sandbox dell'applicazione di un'applicazione iOS, ad esempio, contiene il bundle dell'applicazione, che non è vero per le applicazioni OS X. Le ragioni di queste differenze sono principalmente storiche.
Il sistema operativo installa ogni applicazione iOS in una directory sandbox, che contiene la directory del bundle dell'applicazione e tre directory aggiuntive, Documenti, Biblioteca, e tmp. La directory sandbox dell'applicazione, spesso denominata casa directory, è possibile accedere chiamando una semplice funzione Foundation, NSHomeDirectory ()
.
NSLog (@ "HOME>% @", NSHomeDirectory ());
Puoi provare da solo. Creare un nuovo progetto Xcode basato sul Applicazione vista singola modello e chiamarlo Persistenza dei dati.
Aperto TSPAppDelegate.m e aggiungi lo snippet di codice sopra a applicazione: didFinishLaunchingWithOptions:
.
Se si esegue l'applicazione in iOS Simulator, l'output nella console sarà simile all'output mostrato di seguito.
2014-03-27 09: 48: 16.794 Persistenza dei dati [1426: 60b] HOME> / Utenti / Bart / Libreria / Supporto applicazioni / Simulatore iPhone / 7.1 / Applicazioni / 5024403A-C65E-44DD-BCD2-F93097FB502E
Tuttavia, se si esegue l'applicazione su un dispositivo fisico, l'output appare un po 'diverso, come si può vedere di seguito. Tuttavia, la sandbox dell'applicazione e le limitazioni imposte sono identiche.
2014-03-27 09: 48: 51.571 Persistenza dei dati [1426: 60b] HOME> / var / mobile / Applicazioni / A4D17A73-84D7-4628-9E32-AEFEA5EE6153
Recupero del percorso per l'applicazione Documenti la directory richiede un po 'più di lavoro, come puoi vedere nello snippet di codice qui sotto.
NSArray * directories = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documents = [directory firstObject]; NSLog (@ "DOCUMENTI>% @", documenti);
Noi usiamo il NSSearchPathForDirectoriesInDomains ()
funzione e passare il NSDocumentDirectory
costante come primo argomento per indicare che siamo interessati solo alle applicazioni Documenti directory. Il secondo e il terzo argomento sono di minore importanza per questa discussione. La funzione restituisce un'istanza di NSArray
contenente un risultato, il percorso per l'applicazione Documenti elenco.
Forse ti starai chiedendo perché lo uso firstObject
invece di objectAtIndex:
per recuperare il primo e unico oggetto nella serie di percorsi. Anche se posso essere abbastanza sicuro che l'array restituito non sia vuoto, se l'array dovesse essere vuoto e l'array riceverebbe un messaggio di objectAtIndex:
con una discussione di 0
, l'applicazione si arresterebbe in modo anomalo a causa di un'eccezione non rilevata.
A chiamata firstObject
sull'array, tuttavia, l'array ritorna zero
se non contiene oggetti, significa che non verrà lanciata alcuna eccezione. Ricorda, la documentazione è tua amica.
Qual è il vantaggio della sandboxing? La ragione principale per le applicazioni di sandboxing è la sicurezza. Confinando le applicazioni nella propria sandbox, le applicazioni compromesse non possono causare danni al sistema operativo o ad altre applicazioni.
Di compromessa applicazioni, intendo entrambe le applicazioni che sono state compromesse, le applicazioni che sono intenzionalmente dannose, così come le applicazioni che contengono bug critici che potrebbero inavvertitamente causare danni.
Anche se le applicazioni sono in modalità sandbox sulla piattaforma iOS, le applicazioni iOS possono richiedere l'accesso a determinati file o risorse che si trovano all'esterno della sandbox dell'applicazione tramite una serie di interfacce di sistema.
Un esempio di ciò è la libreria musicale memorizzata su un dispositivo iOS. Sappi, tuttavia, che i framework di sistema sono responsabili di qualsiasi operazione relativa ai file in tali occasioni.
Anche se puoi fare praticamente tutto quello che vuoi nella sandbox dell'applicazione, Apple ha fornito alcune linee guida su ciò che dovrebbe essere archiviato dove. È importante conoscere queste linee guida per diversi motivi. Quando un dispositivo iOS viene eseguito il backup da iTunes, non tutti i file nella sandbox di un'applicazione sono inclusi nel backup.
Il tmp la directory, ad esempio, dovrebbe essere utilizzata solo per la memorizzazione temporanea di file. Il sistema operativo è libero di svuotare questa directory in qualsiasi momento, ad esempio, quando il dispositivo ha poco spazio sul disco. Il tmp la directory non è inclusa nei backup.
Il Documenti directory è pensata per i dati dell'utente, mentre il Biblioteca la directory viene utilizzata per i dati dell'applicazione che non sono strettamente legati all'utente. Il caches directory nel Biblioteca directory è un'altra directory che non è supportata da iTunes.
Inoltre, tieni presente che l'applicazione non dovrebbe modificare il contenuto della directory del pacchetto dell'applicazione. La directory del bundle dell'applicazione viene firmata quando viene installata l'applicazione. Modificando in qualsiasi modo il contenuto della directory del bundle dell'applicazione, la firma di cui sopra viene alterata, il che significa che il sistema operativo non consente il riavvio dell'applicazione. Questa è un'altra misura di sicurezza messa in atto da Apple per proteggere i consumatori.
Esistono diverse strategie per la memorizzazione dei dati delle applicazioni su disco. In questo articolo, diamo una breve occhiata a quattro approcci comuni su iOS:
Le opzioni descritte in questo articolo non devono essere considerate come intercambiabili. Ogni strategia ha i suoi vantaggi e i suoi inconvenienti. Iniziamo dando un'occhiata al sistema di default dell'utente.
Il sistema di default dell'utente è qualcosa che iOS ha ereditato dal sistema operativo X. Anche se è stato creato e progettato per memorizzare le preferenze dell'utente, può essere utilizzato per archiviare qualsiasi tipo di dati purché sia un tipo di elenco di proprietà, NSString
, NSNumber
, NSDate
, NSArray
, NSDictionary
, e NSData
, o una delle loro varianti mutabili.
Il database predefinito dell'utente è nient'altro che una raccolta di elenchi di proprietà, un elenco di proprietà per applicazione. L'elenco delle proprietà è memorizzato in una cartella denominata Preferenze nell'applicazione Biblioteca cartella, che suggerisce lo scopo e la funzione della lista di proprietà.
Uno dei motivi per cui agli sviluppatori piace il sistema di default dell'utente è perché è così facile da usare. Dai un'occhiata al frammento di codice qui sotto per vedere cosa intendo.
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setBool: YES forKey: @ "Key1"]; [userDefaults setInteger: 123 forKey: @ "Key2"]; [userDefaults setObject: @ "Some Object" forKey: @ "Key3"]; [userDefaults boolForKey: @ "Key1"]; [userDefaults integerForKey: @ "Key2"]; [userDefaults objectForKey: @ "Key3"]; [userDefaults synchronize];
Chiamando il standardUserDefaults
metodo di classe su NSUserDefaults
, viene restituito un riferimento all'oggetto default condiviso.
Nell'ultima riga, chiamiamo sincronizzare
sull'oggetto condiviso predefinito per scrivere eventuali modifiche sul disco. Raramente è necessario invocare sincronizzare
, perché il sistema di default dell'utente salva le modifiche quando necessario. Tuttavia, se si memorizza o si aggiorna un'impostazione utilizzando il sistema di default dell'utente, a volte può essere utile o necessario salvare esplicitamente le modifiche sul disco.
A prima vista, il sistema di default dell'utente sembra essere nient'altro che un archivio di valori-chiave situato in una posizione specifica. comunque, il NSUserDefaults
la classe, definita nel framework Foundation, è più di un'interfaccia per la gestione di un archivio di valori-chiave. Dai un'occhiata al suo riferimento di classe per maggiori informazioni.
Prima di procedere, incollare lo snippet di codice sopra nel delegato dell'applicazione applicazione: didFinishLaunchingWithOptions:
metodo ed eseguire l'applicazione in iOS Simulator. Apri una nuova finestra del Finder e vai a Libreria> Supporto applicazioni> iPhone Simulator> 7.1> Applicazioni (sostituire "7.1" con l'ultima versione di iOS).
Trova la cartella dell'applicazione che corrisponde all'applicazione controllando le diverse cartelle con nome criptico nel file applicazioni cartella. La cartella con nome criptico è in realtà la directory sandbox dell'applicazione. Nella directory sandbox dell'applicazione, apri il Preferenze cartella, situata nel Biblioteca cartella e ispezionarne il contenuto.
Dovresti vedere un elenco di proprietà con un nome identico all'identificativo del pacchetto dell'applicazione. Questo è l'archivio predefinito dell'utente per la tua applicazione.
Se vuoi facilitare l'accesso alla sandbox di un'applicazione in iOS Simulator, ti consiglio vivamente di dare un'occhiata a SimPholders. È un'utilità gratuita che semplifica il lavoro con iOS Simulator.
Abbiamo già trattato gli elenchi di proprietà in questa serie. Di fatto, il backing store del database di default dell'utente è un elenco di proprietà. L'utilizzo degli elenchi di proprietà è una comoda strategia per archiviare e recuperare un grafico dell'oggetto. Gli elenchi di proprietà esistono da secoli, sono facili da usare e sono quindi un'ottima opzione per la memorizzazione dei dati in un'applicazione iOS.
Come ho detto prima, è importante tenere presente che un elenco di proprietà può solo memorizzare i dati dell'elenco delle proprietà. Questo significa che non è possibile memorizzare oggetti del modello personalizzato utilizzando gli elenchi di proprietà? No, è possibile. Tuttavia, gli oggetti del modello personalizzato devono essere archiviati, una forma di serializzazione, prima che possano essere archiviati in un elenco di proprietà. Archiviare un oggetto significa semplicemente che l'oggetto deve essere convertito in un tipo di dati che può essere memorizzato in un elenco di proprietà, ad esempio un NSData
esempio.
Ti ricordi di NSCoding
protocollo definito nel framework Foundation? Il NSCoding
il protocollo definisce due metodi,initWithCoder:
e encodeWithCoder:
, che una classe deve implementare per consentire alle istanze della classe di essere codificate e decodificate.
La codifica e la decodifica sono i meccanismi sottostanti per l'archiviazione e la distribuzione degli oggetti. Il modo in cui i lavori di archiviazione degli oggetti saranno chiariti un po 'più avanti in questa serie. In questa lezione, ti mostro solo come scrivere array e dizionari su disco usando liste di proprietà.
Il seguente frammento di codice dovrebbe darti un'idea di quanto sia facile scrivere un array o un dizionario su disco. In teoria, il grafico dell'oggetto memorizzato in un elenco di proprietà può essere tanto complesso quanto largo. Tuttavia, tieni presente che gli elenchi di proprietà non sono pensati per memorizzare decine o centinaia di megabyte di dati, il tentativo di usarli in questo modo rischia di compromettere le prestazioni.
NSArray * fruits = @ [@ "Apple", @ "Mango", @ "Pineapple", @ "Plum", @ "Apricot"]; NSString * filePathFruits = [documenti stringByAppendingPathComponent: @ "fruits.plist"]; [fruits writeToFile: filePathFruits atomically: YES]; NSDictionary * miscDictionary = @ @ "anArray": fruits, @ "aNumber": @ 12345, @ "aBoolean": @ YES; NSString * filePathDictionary = [documenti stringByAppendingPathComponent: @ "misc-dictionary.plist"]; [miscDictionary writeToFile: filePathDictionary atomically: YES]; NSArray * loadedFruits = [NSArray arrayWithContentsOfFile: filePathFruits]; NSLog (@ "Fruits Array>% @", loadedFruits); NSDictionary * loadedMiscDictionary = [Dizionario NSDictionaryWithContentsOfFile: filePathDictionary]; NSLog (@ "Dizionario vari>% @", loadedMiscDictionary);
Diamo un'occhiata allo snippet di codice sopra. Iniziamo memorizzando un riferimento a un array letterale in una variabile denominata frutta
. Creiamo il percorso del file per la memorizzazione della lista di proprietà che stiamo per realizzare. Il percorso del file viene creato aggiungendo una stringa al percorso del file di Documenti directory, che abbiamo recuperato in precedenza in questa lezione. La stringa che aggiungiamo sarà il nome della lista di proprietà, inclusa la sua estensione, .plist-che creeremo in un secondo.
Scrivere la matrice su disco è facile come chiamare writeToFile: atomicamente:
sull'array. Puoi ignorare il atomicamente
bandiera per ora.
Come mostra l'esempio, la scrittura di un dizionario su disco segue uno schema simile. L'esempio illustra anche come creare array e dizionari da un elenco di proprietà, ma questo è qualcosa che abbiamo già trattato in precedenza in questa serie.
Esegui l'applicazione in iOS Simulator e vai alle applicazioni Documenti directory come abbiamo visto in precedenza. In questa directory, dovresti vedere i due elenchi di proprietà che abbiamo appena creato.
Se la tua applicazione è basata su dati e funziona con grandi quantità di dati, allora potresti voler esaminare SQLite. Cos'è SQLite? La tagline sul sito web di SQLite recita "Piccolo, veloce, affidabile, scegli uno qualsiasi tre.", Che riassume bene.
SQLite è una libreria che implementa un database relazionale integrato leggero. Come suggerisce il nome, si basa sullo standard SQL (Structured Query Language) proprio come MySQL e PostgreSQL.
La principale differenza con altri database SQL è che SQLite è portatile, molto leggero e che è privo di server anziché di un processo separato a cui si accede dall'applicazione client. In altre parole, è incorporato nell'applicazione e quindi molto veloce.
Il sito Web di SQLite afferma che si tratta del database SQL più diffuso. Non so se questo è ancora il caso, ma è certamente una scelta popolare per l'archiviazione dei dati lato client. Aperture e iPhoto, ad esempio, si affidano a SQLite per alcuni dei propri archivi di dati.
Il vantaggio che SQLite ha sul lavorare direttamente con gli oggetti è che SQLite è più veloce di un ordine di grandezza, che è in gran parte dovuto al modo in cui i database relazionali e i linguaggi di programmazione orientati agli oggetti differiscono fondamentalmente.
Per colmare il divario tra SQLite e Objective-C, un certo numero di Mappatura relazionale oggettuale (ORM) le soluzioni sono state create nel tempo. L'ORM che Apple ha creato per iOS e OS X è chiamato Dati principali, di cui daremo un'occhiata più avanti in questa lezione.
Usare SQLite su iOS significa lavorare con una libreria basata su C. Se preferisci una soluzione orientata agli oggetti, consiglio vivamente il wrapper Objective-C di Gus Mueller (Flying Meat, Inc.) per SQLite, FMDB.
Rende il lavoro con SQLite molto più semplice se preferisci un'interfaccia orientata agli oggetti. La libreria supporta ARC (Conteggio di riferimento automatico) fuori dalla scatola ed è molto performante. Ho usato FMDB in passato e sono stato molto contento della sua API e della robustezza e affidabilità della libreria.
Gli sviluppatori nuovi di Core Data spesso confondono Core Data per un database mentre si tratta di una soluzione di mapping relazionale di oggetti creata e gestita da Apple. Matt Gallagher ha scritto un ottimo post sulle differenze tra Core Data e un database. Core Data fornisce un modello relazionale orientato agli oggetti che può essere serializzato in un archivio XML, binario o SQLite. Core Data supporta anche un archivio in memoria.
Perché dovresti usare Core Data invece di SQLite? Ponendo questa domanda, si assume erroneamente che i dati fondamentali siano un database. Il vantaggio dell'utilizzo di Core Data è che si lavora con gli oggetti anziché con dati grezzi, come le righe in un database SQLite o i dati memorizzati in un file XML. Anche se Core Data ha avuto alcuni anni difficili quando è stato rilasciato per la prima volta, è diventato un framework robusto con molte funzionalità, come le migrazioni automatiche, il rilevamento delle modifiche, l'errore e la convalida integrata.
Un'altra grande caratteristica apprezzata da molti sviluppatori è l'editor del modello Core Data integrato in Xcode che consente agli sviluppatori di modellare il proprio modello di dati tramite un'interfaccia grafica.
Indipendentemente dal fatto che Core Data sia la soluzione giusta per la tua applicazione, dipende dai dati che prevedi di gestire, sia in termini di quantità che di modello sottostante. Se si prevede di gestire set di dati estremamente grandi, Core Data potrebbe diventare un collo di bottiglia per le prestazioni nel tempo. In tal caso, SQLite potrebbe essere una soluzione migliore.
Probabilmente hai sentito parlare di iCloud e potresti chiederti dove iCloud si inserisce nella storia della persistenza dei dati. iCloud non è una forma di persistenza dei dati come SQLite o Core Data. Invece, è una piattaforma o un servizio per rendere disponibili i dati utente su più dispositivi e più istanze di un'applicazione o persino una famiglia di applicazioni.
La piattaforma iCloud comprende diversi servizi o componenti. Il componente che ci interessa è iCloud Storage, che include tre tipi di archiviazione:
Se vuoi saperne di più su iCloud Storage, ti consiglio di leggere una serie su iCloud Storage che ho scritto all'inizio di quest'anno.
Ora dovresti avere una buona idea delle opzioni che hai in termini di persistenza dei dati durante lo sviluppo per la piattaforma iOS. Tieni presente che non tutte le strategie che abbiamo trattato sono uguali.
Questa serie sta lentamente arrivando alla fine. Nelle prossime due puntate, creeremo un'altra applicazione per mettere in pratica ciò che abbiamo imparato finora. Il modo migliore per imparare è farlo.