La persistance des données lors du lancement des applications est une exigence de la plupart des applications iOS, du stockage des préférences utilisateur à l'aide du système par défaut à la gestion de grands ensembles de données dans une base de données relationnelle. Dans cet article, nous allons explorer les stratégies les plus courantes utilisées pour stocker des données dans une application iOS. Je parlerai également du système de fichiers sur iOS et de la façon dont le sandboxing des applications affecte la persistance des données.
Vous avez parcouru un long chemin, sauterelle, et vous avez beaucoup appris. Cependant, il existe un aspect essentiel du développement iOS dont nous n'avons pas encore discuté, la persistance des données. Pratiquement toutes les applications iOS stockent des données pour une utilisation ultérieure. Les données stockées dans vos magasins d'applications iOS peuvent être n'importe quoi, des préférences de l'utilisateur aux caches temporaires ou même aux grands ensembles de données relationnels..
Avant de discuter des stratégies de persistance des données les plus courantes utilisées par les développeurs sur la plate-forme iOS, je vais d'abord passer quelques minutes à discuter du système de fichiers et du concept de sandboxing d'applications. Pensiez-vous réellement pouvoir stocker les données de votre application où vous le souhaitez sur le système de fichiers? Repensez-vous, padawan.
La sécurité sur la plate-forme iOS fait partie des priorités d'Apple depuis l'introduction de l'iPhone en 2007. Contrairement aux applications OS X, une application iOS est placée dans un sandbox d'applications. Contrairement à ce que la plupart des gens pensent, le sandbox d'une application ne fait pas uniquement référence au répertoire sandbox de cette application dans le système de fichiers. Le sandbox de l’application inclut également un accès contrôlé et limité aux données utilisateur stockées sur le périphérique, les services système et le matériel..
Avec l'introduction du Mac App Store, Apple a également commencé à appliquer le sandboxing des applications sous OS X. Même si les contraintes imposées aux applications OS X ne sont pas aussi strictes que celles imposées aux applications iOS, le concept général est similaire mais non identique. Le sandbox d'application d'une application iOS, par exemple, contient le groupe d'applications, ce qui n'est pas le cas pour les applications OS X. Les raisons de ces différences sont principalement historiques.
Le système d'exploitation installe chaque application iOS dans un répertoire de bac à sable, qui contient le répertoire de l'ensemble d'applications et trois répertoires supplémentaires., Les documents, Bibliothèque, et tmp. Le répertoire sandbox de l'application, souvent appelé son répertoire maison répertoire, accessible en appelant une simple fonction Foundation, NSHomeDirectory ()
.
NSLog (@ "HOME>% @", NSHomeDirectory ());
Vous pouvez essayer cela vous-même. Créez un nouveau projet Xcode basé sur le Application à vue unique modèle et nommez-le Persistance des données.
Ouvrir TSPAppDelegate.m et ajoutez l'extrait de code ci-dessus à application: didFinishLaunchingWithOptions:
.
Si vous exécutez l'application dans le simulateur iOS, la sortie de la console ressemblera à celle affichée ci-dessous..
2014-03-27 09: 48: 16.794 Data Persistence [1426: 60b] ACCUEIL> / Utilisateurs / Bart / Bibliothèque / Support d'application / iPhone Simulator / 7.1 / Applications / 5024403A-C65E-44DD-BCD2-F93097FB502E
Toutefois, si vous exécutez l'application sur un périphérique physique, la sortie est un peu différente, comme vous pouvez le voir ci-dessous. Le sandbox d’application et les limitations imposées sont identiques.
2014-03-27 09: 48: 51.571 Persistance des données [1426: 60b] ACCUEIL> / var / mobile / Applications / A4D17A73-84D7-4628-9E32-AEFEA5EE6153
Récupérer le chemin d'accès à l'application Les documents répertoire nécessite un peu plus de travail comme vous pouvez le voir dans l'extrait de code ci-dessous.
NSArray * répertoires = NSSearchPathForDirectoriesInDomains (NSDocumentDirectory, NSUserDomainMask, YES); NSString * documents = [répertoires firstObject]; NSLog (@ "DOCUMENTS>% @", documents);
Nous utilisons le NSSearchPathForDirectoriesInDomains ()
fonction et passe le NSDocumentDirectory
constante comme premier argument pour indiquer que nous ne sommes intéressés que par l'application Les documents annuaire. Les deuxième et troisième arguments sont moins importants pour cette discussion. La fonction retourne une instance de NSArray
contenant un résultat, le chemin d'accès à l'application Les documents annuaire.
Vous vous demandez peut-être pourquoi j'utilise firstObject
au lieu de objectAtIndex:
chercher le premier et unique objet dans le tableau de chemins. Même si je peux être sûr que le tableau retourné n'est pas vide, si le tableau était vide et qu'il recevrait un message objectAtIndex:
avec un argument de 0
, l'application se planterait en raison d'une exception non interceptée.
En appelant firstObject
sur le tableau, cependant, le tableau retourne néant
s'il ne contient aucun objet, cela signifie qu'aucune exception ne sera levée. N'oubliez pas que la documentation est votre amie.
Quel est l'avantage du sandboxing? La sécurité est la raison principale des applications en bac à sable. En confinant les applications à leur propre sandbox, les applications compromises ne peuvent pas endommager le système d'exploitation ou d'autres applications..
Par compromis les applications, je veux dire les applications qui ont été piratées, les applications qui sont intentionnellement malveillantes, ainsi que les applications qui contiennent des bogues critiques qui peuvent causer des dommages par inadvertance.
Même si les applications sont en mode bac à sable sur la plate-forme iOS, les applications iOS peuvent demander l'accès à certains fichiers ou actifs en dehors de leur sandbox d'application via plusieurs interfaces système..
Un exemple de ceci est la bibliothèque de musique stockée sur un périphérique iOS. Sachez toutefois que les infrastructures système sont chargées de toutes les opérations liées aux fichiers dans de telles circonstances..
Même si vous pouvez faire à peu près tout ce que vous voulez dans le bac à sable de votre application, Apple a fourni quelques instructions concernant ce qui devrait être stocké où. Il est important de connaître ces directives pour plusieurs raisons. Lorsqu'un périphérique iOS est sauvegardé par iTunes, tous les fichiers du sandbox d'une application ne sont pas inclus dans la sauvegarde..
le tmp répertoire, par exemple, ne devrait être utilisé que pour stocker temporairement des fichiers. Le système d'exploitation est libre de vider ce répertoire à tout moment, par exemple lorsque le périphérique manque d'espace disque. le tmp le répertoire n'est pas inclus dans les sauvegardes.
le Les documents répertoire est destiné aux données utilisateur, alors que le Bibliothèque Le répertoire est utilisé pour les données d'application qui ne sont pas strictement liées à l'utilisateur. le Les caches répertoire dans le Bibliothèque Le répertoire est un autre répertoire qui n'est pas sauvegardé par iTunes..
Notez également que votre application n'est pas supposée modifier le contenu du répertoire de l'ensemble d'applications. Le répertoire de l'ensemble d'applications est signé lors de l'installation de l'application. En modifiant de quelque manière que ce soit le contenu du répertoire de l'ensemble d'applications, la signature susmentionnée est modifiée, ce qui signifie que le système d'exploitation ne permet pas à l'application de se relancer. Ceci est une autre mesure de sécurité mise en place par Apple pour protéger les consommateurs.
Il existe plusieurs stratégies pour stocker les données d'application sur le disque. Dans cet article, nous examinons brièvement quatre approches courantes sur iOS:
Les options décrites dans cet article ne doivent pas être considérées comme interchangeables. Chaque stratégie a ses avantages et ses inconvénients. Commençons par jeter un coup d'œil au système par défaut de l'utilisateur.
Le système utilisateur par défaut est un système hérité d’OS X sous iOS. Même s'il a été créé et conçu pour stocker les préférences de l'utilisateur, il peut être utilisé pour stocker tout type de données, à condition qu'il s'agisse d'un type de liste de propriétés., NSString
, NSNumber
, NSDate
, NSArray
, NSDictionary
, et NSData
, ou l'une de leurs variantes mutables.
La base de données par défaut de l'utilisateur n'est rien de plus qu'une collection de listes de propriétés, une liste de propriétés par application. La liste de propriétés est stockée dans un dossier nommé Préférences dans l'application Bibliothèque dossier, qui indique la fonction et le but de la liste de propriétés.
Une des raisons pour lesquelles les développeurs aiment le système par défaut des utilisateurs est leur simplicité d'utilisation. Regardez le fragment de code ci-dessous pour voir ce que je veux dire..
NSUserDefaults * userDefaults = [NSUserDefaults standardUserDefaults]; [userDefaults setBool: YES forKey: @ "Key1"]; [userDefaults setInteger: 123 pourKey: @ "Key2"]; [userDefaults setObject: @ "Un objet" pourKey: @ "Key3"]; [userDefaults boolForKey: @ "Key1"]; [userDefaults integerForKey: @ "Key2"]; [userDefaults objectForKey: @ "Key3"]; [userDefaults synchronize];
En appelant le standardUserDefaults
méthode de classe sur NSUserDefaults
, une référence à l'objet par défaut partagé est renvoyée.
Dans la dernière ligne, nous appelons synchroniser
sur l'objet par défaut partagé pour écrire toutes les modifications sur le disque. Il est rarement nécessaire d'invoquer synchroniser
, parce que le système par défaut de l'utilisateur enregistre les modifications lorsque cela est nécessaire. Toutefois, si vous stockez ou mettez à jour un paramètre à l'aide du système par défaut, il peut parfois être utile ou nécessaire de sauvegarder explicitement les modifications sur le disque..
À première vue, le système par défaut de l'utilisateur ne semble être rien d'autre qu'un magasin de valeurs-clés situé à un emplacement spécifique. Cependant, le NSUserDefaults
La classe, définie dans le framework Foundation, est plus qu'une interface pour la gestion d'un magasin de valeurs-clés. Jetez un oeil à sa référence de classe pour plus d'informations.
Avant de passer à autre chose, collez l’extrait de code ci-dessus dans la liste des délégués de l’application. application: didFinishLaunchingWithOptions:
méthode et exécutez l'application dans le simulateur iOS. Ouvrez une nouvelle fenêtre du Finder et accédez à Bibliothèque> Prise en charge des applications> iPhone Simulator> 7.1> Applications (remplacer "7.1" avec la dernière version d'iOS).
Recherchez le dossier de l’application qui correspond à l’application en inspectant les différents dossiers nommés de manière cryptée dans le dossier. Applications dossier. Le dossier nommé de manière cryptique est en réalité le répertoire sandbox de l'application. Dans le répertoire sandbox de l’application, ouvrez le Préférences dossier, situé dans le Bibliothèque dossier et inspecter son contenu.
Vous devriez voir une liste de propriétés avec un nom identique à l'identifiant de paquet de l'application. Ceci est le magasin par défaut de l'utilisateur pour votre application.
Si vous souhaitez faciliter l'accès au sandbox d'une application dans le simulateur iOS, je vous recommande vivement de jeter un coup d'œil à SimPholders. C'est un utilitaire gratuit qui facilite beaucoup le travail avec le simulateur iOS..
Nous avons déjà traité des listes de propriétés dans cette série. En fait, le magasin de sauvegarde de la base de données par défaut de l'utilisateur est une liste de propriétés. L'utilisation de listes de propriétés est une stratégie pratique pour stocker et récupérer un graphe d'objet. Les listes de propriétés existent depuis longtemps, sont faciles à utiliser et constituent donc une excellente option pour stocker des données dans une application iOS..
Comme je l'ai mentionné précédemment, il est important de garder à l'esprit qu'une liste de propriétés ne peut stocker que des données de liste de propriétés. Cela signifie-t-il qu'il n'est pas possible de stocker des objets de modèle personnalisés à l'aide de listes de propriétés? Non, c'est possible. Toutefois, les objets de modèle personnalisés doivent être archivés (une forme de sérialisation) avant de pouvoir être stockés dans une liste de propriétés. L'archivage d'un objet signifie simplement que l'objet doit être converti en un type de données pouvant être stocké dans une liste de propriétés, telle qu'un fichier. NSData
exemple.
Vous souvenez-vous du NSCoding
protocole défini dans le framework Foundation? le NSCoding
protocole définit deux méthodes,initWithCoder:
et encodeWithCoder:
, qu'une classe doit implémenter pour permettre aux instances de la classe d'être codées et décodées.
L'encodage et le décodage sont les mécanismes sous-jacents d'archivage et de distribution d'objets. La manière dont les travaux d'archives sur les objets seront clarifiés un peu plus tard dans cette série. Dans cette leçon, je vous montre uniquement comment écrire des tableaux et des dictionnaires sur un disque à l'aide de listes de propriétés..
L'extrait de code suivant devrait vous donner une idée de la facilité avec laquelle il est possible d'écrire un tableau ou un dictionnaire sur le disque. En théorie, le graphe d'objets stocké dans une liste de propriétés peut être aussi complexe ou aussi volumineux que vous le souhaitez. Cependant, gardez à l'esprit que les listes de propriétés ne sont pas conçues pour stocker des dizaines ou des centaines de mégaoctets de données. Toute tentative de les utiliser de cette manière entraînera probablement une dégradation des performances..
NSArray * fruits = @ [@ "pomme", @ "mangue", @ "ananas", @ "prune", @ "abricot"]; NSString * filePathFruits = [documents stringByAppendingPathComponent: @ "fruits.plist"]; [fruits writeToFile: filePathFruits atomiquement: OUI]; NSDictionary * miscDictionary = @ @ "anArray": fruits, @ "aNumber": @ 12345, @ "aBoolean": @YES; NSString * filePathDictionary = [documents stringByAppendingPathComponent: @ "misc-dictionary.plist"]; [miscDictionary writeToFile: filePathDictionary de manière atomique: YES]; NSArray * LoadFruits = [NSArray arrayWithContentsOfFile: filePathFruits]; NSLog (@ "Fruits Array>% @", chargedFruits); NSDictionary * LoadedMiscDictionary = [NSDictionary dictionaryWithContentsOfFile: filePathDictionary]; NSLog (@ "Dictionnaire divers>% @", LoadMiscDictionary);
Jetons un coup d'oeil à l'extrait de code ci-dessus. Nous commençons par stocker une référence à un littéral de tableau dans une variable nommée fruits
. Nous créons le chemin de fichier pour stocker la liste de propriétés que nous sommes sur le point de créer. Le chemin du fichier est créé en ajoutant une chaîne au chemin du fichier du Les documents répertoire, que nous avons récupéré plus tôt dans cette leçon. La chaîne que nous ajoutons sera le nom de la liste de propriétés, y compris son extension., .plist-que nous créerons dans une seconde.
L'écriture de la matrice sur le disque est aussi simple que d'appeler writeToFile: atomiquement:
sur le tableau. Vous pouvez ignorer le atomiquement
drapeau pour l'instant.
Comme l'illustre l'exemple, l'écriture d'un dictionnaire sur le disque suit un schéma similaire. L'exemple montre également comment créer des tableaux et des dictionnaires à partir d'une liste de propriétés, mais nous en avons déjà parlé précédemment dans cette série..
Exécutez l’application dans le simulateur iOS et accédez au répertoire de l’application. Les documents répertoire comme nous avons vu plus tôt. Dans ce répertoire, vous devriez voir les deux listes de propriétés que nous venons de créer..
Si votre application est axée sur les données et fonctionne avec de grandes quantités de données, vous voudrez peut-être examiner SQLite. Qu'est-ce que SQLite? Sur le site Web de SQLite, le slogan se lit "Petit. Rapide. Fiable. Choisissez-en trois.", Ce qui résume bien.
SQLite est une bibliothèque qui implémente une base de données relationnelle incorporée légère. Comme son nom l'indique, il est basé sur le standard SQL (Langage d'interrogation structuré) comme MySQL et PostgreSQL.
La principale différence avec les autres bases de données SQL réside dans le fait que SQLite est portable, très léger et qu’il est sans serveur au lieu d’un processus séparé auquel on accède à partir de l’application client. En d'autres termes, il est intégré à l'application et donc très rapide.
Le site Web SQLite affirme qu'il s'agit de la base de données SQL la plus largement déployée. Je ne sais pas si c'est toujours le cas, mais c'est certainement un choix populaire pour le stockage de données côté client. Aperture et iPhoto, par exemple, font appel à SQLite pour le stockage de leurs données..
L'avantage de SQLite par rapport au travail direct avec les objets est que SQLite est beaucoup plus rapide, ce qui est dû en grande partie aux différences fondamentales entre les bases de données relationnelles et les langages de programmation orientés objet..
Pour combler le fossé entre SQLite et Objective-C, un certain nombre de Cartographie relationnelle d'objet (ORM) des solutions ont été créées au fil du temps. L'ORM créé par Apple pour iOS et OS X est nommé Données de base, que nous verrons plus tard dans cette leçon.
Utiliser SQLite sur iOS signifie travailler avec une bibliothèque basée sur C. Si vous préférez une solution orientée objet, je vous recommande vivement l'encapsuleur Objective-C de Gus Mueller (Flying Meat, Inc.) pour SQLite, FMDB..
Travailler avec SQLite est beaucoup plus facile si vous préférez une interface orientée objet. La bibliothèque prend en charge ARC (Comptage automatique des références) hors de la boîte et est très performant. J'ai utilisé FMDB par le passé et je suis très satisfait de son API, de la robustesse et de la fiabilité de la bibliothèque..
Les développeurs qui découvrent Core Data confondent souvent Core Data avec une base de données alors qu’il s’agit vraiment d’une solution de mappage relationnel objet créée et maintenue par Apple. Matt Gallagher a écrit un excellent article sur les différences entre les données de base et une base de données. Core Data fournit un modèle orienté objet relationnel pouvant être sérialisé dans un magasin XML, binaire ou SQLite. Core Data prend même en charge un magasin en mémoire.
Pourquoi devriez-vous utiliser Core Data au lieu de SQLite? En posant cette question, vous supposez à tort que Core Data est une base de données. L'utilisation de Core Data présente l'avantage de pouvoir utiliser des objets plutôt que des données brutes, telles que des lignes dans une base de données SQLite ou des données stockées dans un fichier XML. Même si Core Data avait connu des années difficiles au moment de sa première sortie, il s'est développé en un framework robuste avec de nombreuses fonctionnalités, telles que les migrations automatiques, le suivi des modifications, les défaillances et la validation intégrée..
Une autre fonctionnalité intéressante que beaucoup de développeurs apprécient est l'éditeur de modèle de données Core intégré à Xcode, qui permet aux développeurs de modéliser leur modèle de données via une interface graphique..
Que Core Data soit la bonne solution pour votre application dépend des données que vous prévoyez de gérer, à la fois en termes de quantité et de modèle sous-jacent. Si vous envisagez de gérer des ensembles de données extrêmement volumineux, Core Data peut devenir un goulot d'étranglement au niveau des performances. Dans ce cas, SQLite peut être une meilleure solution.
Vous avez probablement entendu parler d'iCloud et vous vous demandez peut-être où iCloud s'inscrit dans l'histoire de la persistance des données. iCloud n'est pas une forme de persistance des données, contrairement à SQLite ou Core Data. Il s'agit plutôt d'une plate-forme ou d'un service permettant de rendre les données utilisateur disponibles sur plusieurs périphériques et plusieurs instances d'une application, voire une famille d'applications..
La plate-forme iCloud englobe plusieurs services ou composants. La composante qui nous intéresse est Stockage iCloud, qui comprend trois types de stockage:
Si vous voulez en savoir plus sur le stockage iCloud, je vous recommande de lire une série sur le stockage iCloud que j'ai écrite plus tôt cette année..
Vous devriez maintenant avoir une bonne idée des options dont vous disposez en termes de persistance des données lors du développement pour la plate-forme iOS. Gardez à l'esprit que toutes les stratégies que nous avons couvertes ne sont pas égales.
Cette série se termine lentement. Dans les deux prochaines tranches, nous allons créer une autre application pour mettre en pratique ce que nous avons appris jusqu'à présent. La meilleure façon d'apprendre est en faisant.