为什么当我尝试在这些点上做Core Data初始化失败? [英] Why does Core Data initialization fail when I attempt to do it at these points?

查看:149
本文介绍了为什么当我尝试在这些点上做Core Data初始化失败?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我看到如何解决问题,但它困扰我,我不明白为什么这不工作。我有一个UIViewController子类使用Core Data,所以它需要NSManagedObjectContext。



我试着在initWithCoder和viewDidLoad中做这个操作,并且由于某种原因,它是由一个nib文件加载的,它放在一个导航控制器下面。不工作:

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

由于某种原因,managedObjectContext返回nil,当我稍后尝试创建一个托管对象时, / p>

***由于未捕获异常NSInternalInconsistencyException而终止应用程序,原因:'+ entityForName:在此模型中找不到名为LogRecord的实体。



当您的上下文为nil或模型无法加载(或真的缺少实体)时,您会得到这些。



如果我在saveLogEntry方法的顶部做同样的事情(创建托管对象并保存上下文),那么它的工作正常。



如果我做示例应用程序做的事:

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

loggingViewController.managedObjectContext = self.managedObjectContext;

//标准的东西
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}

(loggingViewController是应用程式委托中的IBOutlet)。



有人知道这里可能会发生什么吗?如果太早,但是特别是与viewDidLoad我认为它会工作,因为我认为发生在addSubview被调用后,它似乎失败。

解决方案

做正确的食谱应用程序。



如果你在initWithCoder中尝试,你不知道应用程序委托是否完成初始化它没有)



如果你尝试它viewDidLoad,你有一个类似的问题。



为什么您应访问应用程式委托,例如:

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

这是一个糟糕的表单。它将耦合引入到您的设计中。使用依赖注入,就像示例。



因为从应用程式委托,你知道已经执行了什么初始化,并且可以在适当的时间传递上下文。






更新:



问题是您的View Controller实例很可能在Mainwindow.xib中实例化。 Mainwindow.xib(和其引用的任何其他nib)在应用程序委托接收UIApplicationDidFinishLaunchingNotification通知之前是解冻。



不保证对象从nibs解冻的顺序。当在View Controller上调用initWithCoder:时,你不知道其他对象是否从nib中解冻。您也无法确定应用程式委托是否已收到UIApplicationDidFinishLaunchingNotification通知。



这与viewDidLoad类似。在viewDidLoad中,可以确保nib中的所有其他对象都已正确解冻和初始化,但由于应用程序委托的配置发生在nib文件之外,因此无法确定调用应用程序是否安全delegate。



更好的做法是让应用程序代理在上下文中传递,当它是good and ready时,最好是在applicationDidFinishLaunching:

希望这更清楚一点,你应该看看iphone的编程指南:
http://developer.apple.com/iphone/library/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/index.html



要更好地解释iPhone应用程序的生命周期。



希望有所帮助。






一次更新:



关于iphone发射序列的讨论:
http://www.bit- 101.com/blog/?p=2159


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.

解决方案

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

这篇关于为什么当我尝试在这些点上做Core Data初始化失败?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆