Domanda

Sto usando il progetto di esempio CoreDataBooks di Apple come supporto per l'apprendimento dei dati principali.

Ho modificato l'app in modo tale che quando l'app viene caricata mostri prima una pagina di menu, non la tabella di libri (RootViewController).

Ho fatto quanto segue:

Ho creato una pagina di menu nel generatore di interfaccia (solo una vista con un pulsante su di essa)

Il CoreDataBooksAppDelegate.h ora assomiglia a questo:

// 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

Il CoreDataBooksAppDelegate.m è simile al seguente:

#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];
}

Il resto di CoreDataAppDelegete.m rimane invariato.

In MenuViewController quando si fa clic sul pulsante, si verifica la seguente azione:

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

In IB ho modificato MainWindow.xib per chiamare MenuViewController anziché RootViewController.

Quindi, l'app si carica e il menu viene visualizzato correttamente con il pulsante. Facendo clic sul pulsante, l'applicazione si blocca all'interno del viewDidLoad di RootViewController.

Si blocca proprio qui:

- (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");
}

Nella console ricevo quanto segue:

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

Ho letto di questa eccezione ma non conosco i passaggi corretti per risolverlo.

È stato utile?

Soluzione

Ok.

Inserendo il seguente codice all'interno del viewDidLoad di RootViewController si elimina l'errore:

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

Ho trovato qualcuno con un problema simile qui su SO: testo del link

Come ha sottolineato Aryeh in quel post: " In breve, stai cercando di recuperare un'entità da un oggettoContesto che non era stato ancora impostato. Pertanto, le opzioni sono di configurarlo subito o fare altrove nell'app prima che questa vista venga caricata. & Quot;

Altri suggerimenti

In applicationDidFinishLaunching: stai facendo quanto segue:

rootViewController.managedObjectContext = self.managedObjectContext;

Ma non vedo il codice in cui è installato self.managedObjectContext. applicationDidFinishLaunching è chiamato abbastanza presto. Sei sicuro di aver impostato il contesto dell'oggetto gestito?

Hai cambiato del tutto il modello Core Data? Questo errore è comune quando il modello di dati principali per un'app cambia senza cambiare anche il database SQLite sottostante, quindi i dati memorizzati e il modello non sono sincronizzati.

Prova a rimuovere completamente l'app dal simulatore o dal dispositivo di prova, quindi reinstallala e riprova.

Durante il mio sviluppo, non sono riuscito a trovare Entità che ho aggiunto in seguito. Cosa ha funzionato per me: (Fondamentalmente un suggerimento per la sanità mentale :-)

Disinstalla l'app ogni volta che modifichi il modello di dati!

Il modello di dati viene memorizzato nella cache da Core Data tra le installazioni, per assicurarsi che l'integrità rimanga intatta. Elimina l'app dal simulatore / iPhone per poter testare le modifiche.

PS: qualcuno sa come farlo automaticamente?

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top