Um Core Data in einer iOS-Anwendung benutzen zu können, muss man die Komponenten des Core Data-Frameworks instantiieren, was normalerweise im Application Delegate geschieht. Normalerweise wird dort in der Methode didFinishLaunchingWithOptions das erzeugte NSManagedObjectContext-Objekt den View Controllern übergeben, damit diese es für Zugriffe auf die Datenbank nutzen können.
Die Standardlösung, die auch in vielen Dokumenten von Apple noch vorkommt und von der dieser Code stammt, sieht wie folgt aus:
RootViewController *rootViewController = [[RootViewController alloc] initWithStyle:UITableViewStylePlain]; NSManagedObjectContext *context = [self managedObjectContext]; if (!context) { // Handle the error. } // Pass the managed object context to the view controller. rootViewController.managedObjectContext = context;
Diese Lösung funktioniert bei mir auch in fertigen Projekten. Aber nicht in solchen, die ich von Grund auf selbst erstellt habe.
Den Grund dafür habe ich nach längerer Suche nun gefunden: Mit der Einführung des Storyboards in XCode 4.2 hat sich die Art und der Zeitpunkt, wie / an der Views erzeugt werden, geändert. Während die Views früher in dem Application Delegate vom Entwickler erzeugt wurden, werden sie nun automatisch erzeugt.
Das ist aber blöd, wenn der Entwickler bei der Initialisierung das Objekt des zu dem View dazugehörigen View Controllers braucht, um ihm das managedObjectContext-Objekt zu geben. (Eine gute Praktik für Core Data, die Apple selbst vorschlägt.) In obigem Standardbeispiel wird zwar ein Objekt von RootViewControllers erzeugt und das managedObjectContext übergeben, aber etwas später wird eine neue Instanz des RootViewControllers automatisch erzeugt und dann verwendet — und diese hat den Kontext natürlich nicht übergeben bekommen.
Die Lösung habe schließlich in einem anderen Apple-Dokument gefunden — über Google. Im Abschnitt Accessing the First View Controller des Dokuments Converting to Storyboard:
UINavigationController *rootNavigationController = (UINavigationController *)self.window.rootViewController; MyViewController *myViewController = (MyViewController *)[rootNavigationController topViewController];
Über self.window kann man auf die vom Storyboard verwalteten View Controller zugreifen, diese wieder selbst instantiieren und alles klappt wieder wie vorher.
Schreibe einen Kommentar