2009-10-27 5 views
35

J'utilise le projet d'exemple CoreDataBooks d'Apple comme outil d'apprentissage pour les données de base.Core-Data iPhone: impossible de localiser un NSManagedObjectModel

J'ai modifié l'application de sorte que lorsque l'application se charge, je montre d'abord une page de menu - pas la vue de table Books (RootViewController).

Je l'ai fait ce qui suit:

J'ai créé une page de menu constructeur d'interface (juste une vue avec un bouton sur elle)

Le 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 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 de 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 changé le MainWindow.xib d'appeler la MenuViewController plutôt que le RootViewController. Ainsi, l'application se charge et le menu s'affiche correctement avec le bouton. En cliquant sur le bouton, l'application se bloque à l'intérieur de viewDidLoad de RootViewController.

Il plante 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 les éléments suivants:

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

J'ai lu au sujet de cette exception, mais je ne sais pas les mesures appropriées pour le résoudre.

Répondre

87

Ok.

Placer le code suivant à l'intérieur de viewDidLoad du RootViewController élimine l'erreur:

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 le SO: link text

Comme Aryeh a souligné dans ce poste: « Dans Bref, vous essayez de récupérer une entité à partir d'un objectContext qui n'a pas encore été configuré.Vos options sont donc de le configurer immédiatement ou de le faire ailleurs dans l'application avant le chargement de cette vue. "

3

Avez-vous modifié le modèle de base de données? Cette erreur est courante lorsque le modèle de données de base pour une application change sans modifier également la base de données SQLite sous-jacente, 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 périphérique de test, puis réinstallez-la et réessayez.

+0

Salut. Je suis allé jusqu'à réinitialiser le contenu et les paramètres sur le simulateur. Dans Xcode, j'ai vidé le cache et nettoyé toutes les cibles. L'erreur: 'NSInternalInconsistencyException', raison: '+ entityForName: impossible de localiser un NSManagedObjectModel pour le nom d'entité' Book '' se produit toujours. Merci pour votre aide Tim. – CraigH

+1

Parcourez le programme dans le débogueur - quelle est la valeur de 'managedObjectModel' lorsque vous obtenez l'exception? 'managedObjectContext'? – Tim

+0

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

4

En 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ée assez tôt. Êtes-vous sûr de configurer le contexte de l'objet géré?

+0

Salut Doug. Oui, le contexte d'objet géré est configuré (c'est l'exemple CoreDataBooks d'Apple, j'ajoutais juste un menu donc j'ai laissé le reste du code intact). Dans applicationDidFinishLaunching si je remplace la ligne: [window addSubview: viewController.view]; avec la ligne: [window addSubview: [navigationController view]]; (voir ci-dessus dans la publication de mes questions), l'application charge immédiatement RootViewController, s'exécute correctement et managedObjectContext n'est pas nul. De toute façon, dans le fichier applicationDidFinishLaunching, managedObjectContext a une valeur: . Merci. – CraigH

0

Pendant mon développement, je n'ai pas pu trouver les entités que j'ai ajoutées plus tard. Ce qui a fonctionné pour moi: (Fondamentalement un astuce-conseil :-)

Désinstaller 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, pour s'assurer que l'intégrité reste intacte. Supprimez l'application du simulateur/iPhone pour pouvoir tester vos modifications. PS: est-ce que quelqu'un sait comment faire cela automatiquement?

Questions connexes