Um Core Data in einer iOS-Anwen­dung benut­zen zu kön­nen, muss man die Kom­po­nen­ten des Core Data-Frame­works instan­ti­ie­ren, was nor­ma­ler­wei­se im App­li­ca­ti­on Dele­ga­te geschieht. Nor­ma­ler­wei­se wird dort in der Metho­de did­Fi­nishLaun­ching­Wi­th­Op­ti­ons das erzeug­te NSMa­na­ge­d­Ob­ject­Con­text-Objekt den View Con­trol­lern über­ge­ben, damit die­se es für Zugrif­fe auf die Daten­bank nut­zen kön­nen.

Die Stan­dard­lö­sung, die auch in vie­len Doku­men­ten von Apple noch vor­kommt und von der die­ser 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;

Die­se Lösung funk­tio­niert bei mir auch in fer­ti­gen Pro­jek­ten. Aber nicht in sol­chen, die ich von Grund auf selbst erstellt habe.

Den Grund dafür habe ich nach län­ge­rer Suche nun gefun­den: Mit der Ein­füh­rung des Sto­ry­boards in XCode 4.2 hat sich die Art und der Zeit­punkt, wie / an der Views erzeugt wer­den, geän­dert. Wäh­rend die Views frü­her in dem App­li­ca­ti­on Dele­ga­te vom Ent­wick­ler erzeugt wur­den, wer­den sie nun auto­ma­tisch erzeugt.

Das ist aber blöd, wenn der Ent­wick­ler bei der Initia­li­sie­rung das Objekt des zu dem View dazu­ge­hö­ri­gen View Con­trol­lers braucht, um ihm das mana­ge­d­Ob­ject­Con­text-Objekt zu geben. (Eine gute Prak­tik für Core Data, die Apple selbst vor­schlägt.) In obi­gem Stan­dard­bei­spiel wird zwar ein Objekt von Root­View­Con­trol­lers erzeugt und das mana­ge­d­Ob­ject­Con­text über­ge­ben, aber etwas spä­ter wird eine neue Instanz des Root­View­Con­trol­lers auto­ma­tisch erzeugt und dann ver­wen­det — und die­se hat den Kon­text natür­lich nicht über­ge­ben bekom­men.

Die Lösung habe schließ­lich in einem ande­ren Apple-Doku­ment gefun­den — über Goog­le. Im Abschnitt Acces­sing the First View Con­trol­ler des Doku­ments Con­ver­ting to Sto­ry­board:

    UINavigationController *rootNavigationController = (UINavigationController *)self.window.rootViewController;
    MyViewController *myViewController = (MyViewController *)[rootNavigationController topViewController];

Über self.window kann man auf die vom Sto­ry­board ver­wal­te­ten View Con­trol­ler zugrei­fen, die­se wie­der selbst instan­ti­ie­ren und alles klappt wie­der wie vor­her.