35 votes

Core-Data iPhone : Impossible de localiser un NSManagedObjectModel.

J'utilise le projet type CoreDataBooks d'Apple comme aide à l'apprentissage des données de base.

J'ai modifié l'application de façon à ce que, lors du chargement de l'application, j'affiche d'abord une page de menu, et non la vue de la table des livres (RootViewController).

J'ai fait ce qui suit :

J'ai créé une page de menu dans interface builder (juste une vue avec un bouton dessus).

Le fichier CoreDataBooksAppDelegate.h ressemble maintenant à ceci :

// for the menu
@class MenuViewController;

@interface CoreDataBooksAppDelegate : NSObject <UIApplicationDelegate> {

NSManagedObjectModel *managedObjectModel;
NSManagedObjectContext *managedObjectContext;     
NSPersistentStoreCoordinator *persistentStoreCoordinator;

UIWindow *window;
UINavigationController *navigationController;

//for the menu
MenuViewController *viewController;
}

- (IBAction)saveAction:sender;

//for the menu
@property (nonatomic, retain) IBOutlet MenuViewController *viewController;

@property (nonatomic, retain, readonly) NSManagedObjectModel *managedObjectModel;
@property (nonatomic, retain, readonly) NSManagedObjectContext *managedObjectContext;
@property (nonatomic, retain, readonly) NSPersistentStoreCoordinator     *persistentStoreCoordinator;

@property (nonatomic, readonly) NSString *applicationDocumentsDirectory;

@property (nonatomic, retain) IBOutlet UIWindow *window;
@property (nonatomic, retain) IBOutlet UINavigationController *navigationController;

@end

Le fichier CoreDataBooksAppDelegate.m ressemble à ceci :

#import "CoreDataBooksAppDelegate.h"
#import "RootViewController.h"
// for the menu
#import "MenuViewController.h"

@implementation CoreDataBooksAppDelegate

@synthesize window;
@synthesize navigationController;

// for the menu
@synthesize viewController;

#pragma mark -
#pragma mark Application lifecycle

- (void)applicationDidFinishLaunching:(UIApplication *)application {

RootViewController *rootViewController = (RootViewController   *)[navigationController  topViewController];
rootViewController.managedObjectContext = self.managedObjectContext;

// for the menu
[window addSubview:viewController.view];

// Configure and show the window
[window makeKeyAndVisible];
}

Le reste du fichier CoreDataAppDelegete.m reste inchangé.

Dans le MenuViewController, lorsque le bouton est cliqué, l'action suivante a lieu :

RootViewController *modalViewController1 = [[[RootViewController alloc] initWithNibName:nil bundle:nil] autorelease];  
[self presentModalViewController:modalViewController1 animated:YES];

Dans IB, j'ai modifié le fichier MainWindow.xib pour appeler le MenuViewController plutôt que le RootViewController.

Ainsi, l'application se charge et le menu s'affiche correctement avec le bouton. Lorsque l'on clique sur le bouton, l'application se bloque dans le viewDidLoad du RootViewController.

Il s'écrase juste ici :

- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"1 START viewDidLoad RootViewController");
self.title = @"Books";
// Set up the edit and add buttons.
self.navigationItem.leftBarButtonItem = self.editButtonItem;

NSLog(@"2 setup button viewDidLoad RootViewController");
// Configure the add button.
UIBarButtonItem *addButton = [[UIBarButtonItem alloc]   initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self   action:@selector(addBook)];
self.navigationItem.rightBarButtonItem = addButton;
[addButton release];  

NSLog(@"3 viewDidLoad RootViewController");
NSError *error;
// HERE IS THE CRASH SITE
 if (![[self fetchedResultsController] performFetch:&error]) {
  NSLog(@"Does not reach this point in viewDidLoad RootViewController");
  // Update to handle the error appropriately.
  NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
  abort();  // Fail
 }
 NSLog(@"END viewDidLoad RootViewController");
}

Dans la console, je reçois le message suivant :

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an NSManagedObjectModel for entity name 'Book''

J'ai lu des articles sur cette exception mais je ne connais pas les étapes à suivre pour la résoudre.

87voto

CraigH Points 1222

Ok.

En plaçant le code suivant dans le viewDidLoad du RootViewController, l'erreur disparaît :

if (managedObjectContext == nil) 
{ 
    managedObjectContext = [(CoreDataBooksAppDelegate *)[[UIApplication sharedApplication] delegate] managedObjectContext]; 
    NSLog(@"After managedObjectContext: %@",  managedObjectContext);
}

J'ai trouvé quelqu'un avec un problème similaire ici sur SO : texte du lien

Comme Aryeh l'a souligné dans ce post : "En bref, vous essayez d'extraire une entité d'un objectContext qui n'a pas encore été configuré. Vos options sont donc de le configurer à ce moment-là ou de le faire ailleurs dans l'application avant le chargement de cette vue."

4voto

Doug Richardson Points 1386

Dans l'applicationDidFinishLaunching : vous faites ce qui suit :

rootViewController.managedObjectContext = self.managedObjectContext;

Mais je ne vois pas le code où self.managedObjectContext est configuré. applicationDidFinishLaunching est appelé assez tôt. Etes-vous sûr d'avoir configuré le contexte de l'objet géré ?

0 votes

Salut Doug. Oui, le contexte de l'objet géré est configuré (il s'agit de l'échantillon CoreDataBooks d'Apple, je ne faisais qu'ajouter un menu donc j'ai laissé le reste du code intact). Dans l'applicationDidFinishLaunching, si je remplace la ligne : [window addSubview:viewController.view] ; par la ligne : [window addSubview :[navigationController view]] ; (voir ci-dessus dans ma question), l'application charge immédiatement le RootViewController, fonctionne bien et le managedObjectContext n'est pas nul. Dans tous les cas, dans l'applicationDidFinishLaunching, managedObjectContext a une valeur : <NSManagedObjectContext : 0x3e2d030>. Merci.

3voto

Tim Points 33042

Avez-vous modifié le modèle Core Data ? Cette erreur est fréquente lorsque le modèle Core Data d'une application est modifié sans que la base de données SQLite sous-jacente ne soit modifiée, de sorte que les données stockées et le modèle ne sont pas synchronisés.

Essayez de supprimer complètement votre application du simulateur ou du dispositif de test, puis réinstallez-la et réessayez.

0 votes

Bonjour, j'ai été jusqu'à réinitialiser le contenu et les paramètres du simulateur. Dans Xcode, j'ai vidé le cache et nettoyé toutes les cibles. L'erreur : 'NSInternalInconsistencyException', reason : '+entityForName : could not locate an NSManagedObjectModel for entity name 'Book'' se produit toujours. Merci pour votre aide, Tim.

1 votes

Parcourez le programme dans le débogueur - quelle est la valeur de managedObjectModel quand vous recevez l'exception ? managedObjectContext ?

0 votes

Bonjour, dans le débogueur je ne vois pas managedObjectModel - mais ce que je vois c'est que la valeur de managedObjectContext est nulle dans le RootViewController viewDidLoad - ce qui est faux, il devrait avoir une valeur à cet endroit. Dans la version non modifiée de l'application, la valeur de managedObjectContext est 0x3e2ce60 dans le viewDidLoad. et le débogueur s'arrête sur cette ligne : NSEntityDescription *entity = [NSEntityDescription entityForName:@"Book" inManagedObjectContext:managedObjectContext] ; Ce qui se trouve à l'intérieur de la méthode - (NSFetchedResultsController *)fetchedResultsController du RootViewController.

0voto

Luc Bloom Points 107

Au cours de mon développement, je n'ai pas pu trouver les Entités que j'ai ajoutées par la suite. Ce qui a fonctionné pour moi : (essentiellement un conseil de sécurité :-)

Désinstallez l'application CHAQUE FOIS que vous changez le modèle de données !

Le modèle de données est mis en cache par Core Data entre les installations, afin de s'assurer que l'intégrité reste intacte. Supprimez l'application du simulateur / iPhone pour pouvoir tester vos changements.

PS : quelqu'un sait-il comment faire cela automatiquement ?

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X