Hier, j'ai tweeté pour demander des conseils sur la meilleure façon de fournir un ensemble de départ de données dans une base de données basée sur l'application. Le soft, je travaille sur avaient commencé avec juste un petit ensemble de données de départ, donc la première fois le soft a été exécuté, j'ai simplement tiré dans les données de démarrage à partir d'un fichier plist dans le fond et créé des objets gérés en fonction du contenu et de tous était bon. L'utilisateur ne s'en aperçut et la charge était complète avant ils avaient besoin de faire quelque chose avec les données.
Alors l'ensemble des données a obtenu un peu plus grand et que la solution est devenue trop lente. Alors, j'ai demandé au Twitterverse d'opinions sur la meilleure façon de fournir une grande quantité de données à partir d'une application de données de base. Qu'est-ce que j'espérais trouver était de savoir si vous pourriez inclure un magasin persistant dans votre bundle application et l'utilisation plutôt que de créer de nouveaux magasins persistante la première fois l'application lancée.
La réponse est revenu de beaucoup, beaucoup de personnes que vous pourriez, en effet, la copie d'un magasin existant persistante de votre bundle soft. Vous pouvez même créer le stockage persistant en utilisant un Mac de base de cacao de données d'application aussi longtemps que le fichier utilisé xcdatamodel même que votre application iPhone.
Avant que je continue, je tiens à remercier toutes les personnes qui ont répondu avec des suggestions et des conseils. Un merci spécial à Dan Pasco de la boutique de dev excellente Noir Pixel qui a donné une aide très substantielle. Avec l'aide de la communauté iOS dev, il m'a fallu environ 15 minutes pour que ça marche dans une de mes applications actuelles. Plusieurs personnes ont demandé des détails sur Twitter. 140 caractères ne va pas le couper pour cela, mais voici ce que j'ai fait.
D'abord, j'ai créé un nouveau Mac / Cocoa projet dans Xcode. J'ai utilisé le modèle de cacao demande régulière, en veillant à utiliser des données de base. Plusieurs personnes ont également suggéré que vous pourriez utiliser une application Cocoa document-Based utilisant Core Data qui vous permettrait de sauver le magasin persistant partout que tu voulais. Je crée le projet Xcode dans un sous-répertoire de mon projet principal, et j'ai ajouté le fichier du modèle de données et toutes les classes d'objets gérés à partir de mon projet principal dans le nouveau projet en utilisant des références relatives au projet, en veillant à ne pas copier les fichiers dans le nouveau dossier du projet - je veux utiliser les mêmes fichiers que mon projet originel de sorte que toute modification apportée à celui-ci sont répercutées dans l'autre.
Si mes données de départ était changent fréquemment, je serais probablement faire de ce nouveau projet une dépendance de mon projet principal et ajouter une copie des fichiers construire phase qui va copier le stockage persistant dans le dossier du projet principal de ressources, mais mes données ne change pas très souvent, donc je suis juste de le faire manuellement. On peut certainement automatiser la tâche au sein de Xcode, et j'ai entendu de plusieurs personnes qui l'ont fait.
Dans le projet de nouvelle cacao, la première chose à faire est de modifier la méthode persistentStoreCoordinator du délégué app pour qu'il utilise un magasin persistant avec le même nom que votre application iOS. Ceci est la ligne de code dont vous avez besoin de modifier:
Assurez-vous d'ajouter l'extension. Sqlite au nom de fichier. Par défaut, le modèle d'application Cocoa utilise un magasin de données XML et aucune extension de fichier. Le nom du fichier que vous indiquez ici est utilisée exactement, donc si vous voulez une extension de fichier, vous devez le spécifier.
Depuis défaut de cacao du projet d'application d'un magasin basé sur XML persistants, vous devez également modifier le type de magasin de l'App cacao à SQLite. C'est quelques lignes plus tard. Cherchez cette ligne:
Changement d'NSXMLStoreType NSSQLiteStoreType.
En option, vous pouvez aussi changer la méthode applicationSupportDirectory de revenir un autre endroit si vous voulez rendre le stockage persistant plus facile à trouver. Par défaut, il va aller dans les
Ensuite, vous devez faire vos importer des données. Ce code sera intrinsèquement spécifiques à l'application et dépendra de votre modèle de données et les données dont vous avez besoin d'importer. Voici un simple pseudo-méthode pour analyser un fichier texte délimité par des tabulations pour donner une idée à quoi cela pourrait ressembler. Cette méthode crée une NSAutoreleasePool et un contexte pour qu'il puisse être lancé dans un thread si vous le désirez. Vous pouvez également l'appeler directement - il ne dérange en rien.
Vous pouvez ajouter le applicationDidFinishLaunching méthode déléguée: à votre délégué app et de mettre votre code là. Vous n'avez même pas vraiment besoin de vous soucier de combien de temps cela prend - il n'ya pas de processus de surveillance sur le Mac qui tue votre application si elle ne répond pas à des événements après une période de temps. Si vous préférez, vous pouvez avoir votre fonctionnalité d'importation des données de travail dans le fond, bien que depuis l'app ne fait rien d'autre, il n'y a aucun avantage réel, sauf le fait que c'est la «bonne» façon de coder une application.
Maintenant, lancez votre application. Quand c'est fait, l'importation, vous pouvez simplement copier le fichier de stockage persistant dans le projet de votre iOS app Xcode dans le groupe des ressources. Lorsque vous créez votre appli, ce fichier sera automatiquement copié dans votre application bundle. Maintenant, vous avez juste besoin de modifier le délégué app de votre application iOS d'utiliser ce magasin persistante au lieu de créer un nouveau magasin vide persistante la première fois l'application est exécutée.
Pour ce faire, il vous suffit de vérifier l'existence du magasin persistant dans le dossier de votre application / documents, et si elle n'y est pas, vous le copiez le paquet d'application dans le dossier de l'/ Documents avant de créer le magasin persistant. Dans le délégué app, la méthode persistentStoreCoordinator devrait ressembler à ceci:
Et `Voil a! Si vous exécutez l'application pour la première fois sur un périphérique, ou de l'exécuter sur le simulateur après la réinitialisation de contenu et les paramètres, vous devriez commencer avec les données qui ont été chargées dans votre application Cocoa.
Alors l'ensemble des données a obtenu un peu plus grand et que la solution est devenue trop lente. Alors, j'ai demandé au Twitterverse d'opinions sur la meilleure façon de fournir une grande quantité de données à partir d'une application de données de base. Qu'est-ce que j'espérais trouver était de savoir si vous pourriez inclure un magasin persistant dans votre bundle application et l'utilisation plutôt que de créer de nouveaux magasins persistante la première fois l'application lancée.
La réponse est revenu de beaucoup, beaucoup de personnes que vous pourriez, en effet, la copie d'un magasin existant persistante de votre bundle soft. Vous pouvez même créer le stockage persistant en utilisant un Mac de base de cacao de données d'application aussi longtemps que le fichier utilisé xcdatamodel même que votre application iPhone.
Avant que je continue, je tiens à remercier toutes les personnes qui ont répondu avec des suggestions et des conseils. Un merci spécial à Dan Pasco de la boutique de dev excellente Noir Pixel qui a donné une aide très substantielle. Avec l'aide de la communauté iOS dev, il m'a fallu environ 15 minutes pour que ça marche dans une de mes applications actuelles. Plusieurs personnes ont demandé des détails sur Twitter. 140 caractères ne va pas le couper pour cela, mais voici ce que j'ai fait.
D'abord, j'ai créé un nouveau Mac / Cocoa projet dans Xcode. J'ai utilisé le modèle de cacao demande régulière, en veillant à utiliser des données de base. Plusieurs personnes ont également suggéré que vous pourriez utiliser une application Cocoa document-Based utilisant Core Data qui vous permettrait de sauver le magasin persistant partout que tu voulais. Je crée le projet Xcode dans un sous-répertoire de mon projet principal, et j'ai ajouté le fichier du modèle de données et toutes les classes d'objets gérés à partir de mon projet principal dans le nouveau projet en utilisant des références relatives au projet, en veillant à ne pas copier les fichiers dans le nouveau dossier du projet - je veux utiliser les mêmes fichiers que mon projet originel de sorte que toute modification apportée à celui-ci sont répercutées dans l'autre.
Si mes données de départ était changent fréquemment, je serais probablement faire de ce nouveau projet une dépendance de mon projet principal et ajouter une copie des fichiers construire phase qui va copier le stockage persistant dans le dossier du projet principal de ressources, mais mes données ne change pas très souvent, donc je suis juste de le faire manuellement. On peut certainement automatiser la tâche au sein de Xcode, et j'ai entendu de plusieurs personnes qui l'ont fait.
Dans le projet de nouvelle cacao, la première chose à faire est de modifier la méthode persistentStoreCoordinator du délégué app pour qu'il utilise un magasin persistant avec le même nom que votre application iOS. Ceci est la ligne de code dont vous avez besoin de modifier:
NSURL *url = [NSURL fileURLWithPath: [applicationSupportDirectory stringByAppendingPathComponent: @"My_App_Name.sqlite"]];Assurez-vous d'ajouter l'extension. Sqlite au nom de fichier. Par défaut, le modèle d'application Cocoa utilise un magasin de données XML et aucune extension de fichier. Le nom du fichier que vous indiquez ici est utilisée exactement, donc si vous voulez une extension de fichier, vous devez le spécifier.
Depuis défaut de cacao du projet d'application d'un magasin basé sur XML persistants, vous devez également modifier le type de magasin de l'App cacao à SQLite. C'est quelques lignes plus tard. Cherchez cette ligne:
if (![persistentStoreCoordinator addPersistentStoreWithType:NSXMLStoreType
configuration:nil
URL:url
options:nil
error:&error]){Changement d'NSXMLStoreType NSSQLiteStoreType.
En option, vous pouvez aussi changer la méthode applicationSupportDirectory de revenir un autre endroit si vous voulez rendre le stockage persistant plus facile à trouver. Par défaut, il va aller dans les
~/Library/Application Support/[Cocoa App Name]/qui peut être un peu un glisser pour naviguer.
Ensuite, vous devez faire vos importer des données. Ce code sera intrinsèquement spécifiques à l'application et dépendra de votre modèle de données et les données dont vous avez besoin d'importer. Voici un simple pseudo-méthode pour analyser un fichier texte délimité par des tabulations pour donner une idée à quoi cela pourrait ressembler. Cette méthode crée une NSAutoreleasePool et un contexte pour qu'il puisse être lancé dans un thread si vous le désirez. Vous pouvez également l'appeler directement - il ne dérange en rien.
- (void)loadInitialData
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
[context setPersistentStoreCoordinator:self.persistentStoreCoordinator];
NSString *path = [[NSBundle mainBundle] pathForResource:@"foo" ofType:@"txt"];
char buffer[1000];
FILE* file = fopen([path UTF8String], "r");
while(fgets(buffer, 1000, file) != NULL)
{
NSString* string = [[NSString alloc] initWithUTF8String:buffer];
NSArray *parts = [string componentsSeparatedByString:@"\t"]
MyManagedObjectClass *oneObject = [self methodToCreateObjectFromArray:parts];
[string release];
}
NSLog(@"Done initial load");
fclose(file);
NSError *error;
if (![context save:&error])
NSLog(@"Error saving: %@", error);
[context release];
[pool drain];
}Vous pouvez ajouter le applicationDidFinishLaunching méthode déléguée: à votre délégué app et de mettre votre code là. Vous n'avez même pas vraiment besoin de vous soucier de combien de temps cela prend - il n'ya pas de processus de surveillance sur le Mac qui tue votre application si elle ne répond pas à des événements après une période de temps. Si vous préférez, vous pouvez avoir votre fonctionnalité d'importation des données de travail dans le fond, bien que depuis l'app ne fait rien d'autre, il n'y a aucun avantage réel, sauf le fait que c'est la «bonne» façon de coder une application.
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Do import or launch threads to do import
// So, do this:
[self loadInitialData];
// or this:
[self performSelectorInBackground:@selector(loadInitialData) withObject:nil];
// But not both for the same method probably
}Maintenant, lancez votre application. Quand c'est fait, l'importation, vous pouvez simplement copier le fichier de stockage persistant dans le projet de votre iOS app Xcode dans le groupe des ressources. Lorsque vous créez votre appli, ce fichier sera automatiquement copié dans votre application bundle. Maintenant, vous avez juste besoin de modifier le délégué app de votre application iOS d'utiliser ce magasin persistante au lieu de créer un nouveau magasin vide persistante la première fois l'application est exécutée.
Pour ce faire, il vous suffit de vérifier l'existence du magasin persistant dans le dossier de votre application / documents, et si elle n'y est pas, vous le copiez le paquet d'application dans le dossier de l'/ Documents avant de créer le magasin persistant. Dans le délégué app, la méthode persistentStoreCoordinator devrait ressembler à ceci:
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
@synchronized (self)
{
if (persistentStoreCoordinator != nil)
return persistentStoreCoordinator;
NSString *defaultStorePath = [[NSBundle bundleForClass:[self class]] pathForResource:@"My_App_Name" ofType:@"sqlite"];
NSString *storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: @"My_App_Name.sqlite"];
NSError *error;
if (![[NSFileManager defaultManager] fileExistsAtPath:storePath])
{
if ([[NSFileManager defaultManager] copyItemAtPath:defaultStorePath toPath:storePath error:&error])
NSLog(@"Copied starting data to %@", storePath);
else
NSLog(@"Error copying default DB to %@ (%@)", storePath, error);
}
NSURL *storeURL = [NSURL fileURLWithPath:storePath];
persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error])
{
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return persistentStoreCoordinator;
}
}Et `Voil a! Si vous exécutez l'application pour la première fois sur un périphérique, ou de l'exécuter sur le simulateur après la réinitialisation de contenu et les paramètres, vous devriez commencer avec les données qui ont été chargées dans votre application Cocoa.
Aucun commentaire:
Enregistrer un commentaire