Why does Core Data initialization fail when I attempt to do it at these points?

帅比萌擦擦* 提交于 2019-12-20 02:49:22

问题


I see how to solve the problem but it bothers me that I don't understand why this doesn't work. I have a UIViewController subclass that uses Core Data, so it needs the NSManagedObjectContext. The controller is loaded from a nib file where it's placed under a navigation controller which is inside a tab controller.

I tried doing this in initWithCoder and viewDidLoad and for some reason it doesn't work:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = [[appDelegate managedObjectContext] retain];

For some reason managedObjectContext returns nil and I get this when I try to create a managed object later:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '+entityForName: could not locate an entity named 'LogRecord' in this model.'

Which is what you get when your context is nil or the model can't be loaded (or really lacks the entity).

If I do the exact same thing at the top of my saveLogEntry method (which creates managed objects and saves the context) then it works just fine.

If I do what the Recipes sample application does:

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

    loggingViewController.managedObjectContext = self.managedObjectContext;

    // Standard stuff
    [window addSubview:tabBarController.view];
    [window makeKeyAndVisible];
}

(loggingViewController is an IBOutlet in the app delegate).

Does anyone know what specifically might be going on here? It seems like it fails if done "too early" but especially with viewDidLoad I'd expect it to work since I think that occurs after addSubview is called.


回答1:


Do exactly what the recipes app does.

If you try it in initWithCoder, you don't know if the app delegate has finished initialization (which it hasn't)

If you try it viewDidLoad, you have a similar problem.

That is why you should NOT be accessing the app delegate like so:

MyAppDelegate *appDelegate = (MyAppDelegate *)[[UIApplication sharedApplication] delegate];
self.managedObjectContext = [[appDelegate managedObjectContext] retain];

This is bad form. It introduces coupling into your design. Use dependency injection, just like the example. It makes your app more flexible.

Because from the app delegate you know exactly what initialization has been performed and can pass in the context at the appropriate time.


Update:

The issue is that your View Controller instance is likely being instantiated in the Mainwindow.xib. Mainwindow.xib (and any other nibs it references) is "defrosted" before the app delegate receives UIApplicationDidFinishLaunchingNotification notification.

The order in which objects are defrosted from nibs is not guaranteed. When initWithCoder: is called on your View Controller you have no idea what other objects have been defrosted from the nib. You also can't be sure whether the app delegate has received the UIApplicationDidFinishLaunchingNotification notification.

It is similar for viewDidLoad. In viewDidLoad, you can be sure that all other objects in the nib have been properly defrosted and initialized, but since the configuration of the app delegate happens outside of the nib file, you can't be sure whether it is safe to call the app delegate.

It is better just to have the app delegate pass in the context when it is "good and ready", preferably in the applicationDidFinishLaunching: method.

Hope that is a little clearer, you should take a look at the iphone programming guide: http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html

To glean a better explanation of the iPhone application life cycle.

Hope that helps.


One More Update:

In depth discussion of the iphone launch sequence: http://www.bit-101.com/blog/?p=2159



来源:https://stackoverflow.com/questions/2022432/why-does-core-data-initialization-fail-when-i-attempt-to-do-it-at-these-points

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!