当我尝试在这些时间点执行核心数据初始化时,为什么会失败?

发布于 2024-08-17 06:37:56 字数 1134 浏览 6 评论 0原文

我知道如何解决这个问题,但令我困扰的是我不明白为什么这不起作用。我有一个使用 Core Data 的 UIViewController 子类,因此它需要 NSManagedObjectContext。控制器从 nib 文件加载,该文件放置在选项卡控制器内的导航控制器下。

我尝试在 initWithCoder 和 viewDidLoad 中执行此操作,但由于某种原因它不起作用:

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

出于某种原因, ManagedObjectContext 返回 nil ,当我稍后尝试创建托管对象时,我得到了这个:

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

这是当上下文为零或模型无法加载(或确实缺少实体)时得到的结果。

如果我在 saveLogEntry 方法(创建托管对象并保存上下文)的顶部执行完全相同的操作,那么它就可以正常工作。

如果我执行 Recipes 示例应用程序的操作:

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

    loggingViewController.managedObjectContext = self.managedObjectContext;

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

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

有谁知道这里具体发生了什么?如果“太早”完成,它似乎会失败,但特别是对于 viewDidLoad 我希望它能够工作,因为我认为这发生在调用 addSubview 之后。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

爱情眠于流年 2024-08-24 06:37:56

完全按照食谱应用程序的操作进行操作。

如果您在 initWithCoder 中尝试,您不知道应用程序委托是否已完成初始化(实际上尚未完成)。

如果您在 viewDidLoad 中尝试,则会遇到类似的问题。

这就是为什么您不应该像这样访问应用程序委托:

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

这是不好的形式。它将耦合引入到您的设计中。使用依赖注入,就像示例一样。它使您的应用程序更加灵活。

因为从应用程序委托中,您可以确切地知道已经执行了哪些初始化,并且可以在适当的时间传入上下文。


更新:

问题是您的视图控制器实例可能在 Mainwindow.xib 中实例化。 Mainwindow.xib(以及它引用的任何其他 nib)在应用程序委托收到 UIApplicationDidFinishLaunchingNotification 通知之前“解冻”。

不保证物体从碎粒中解冻的顺序。当在视图控制器上调用 initWithCoder: 时,您不知道还有哪些其他对象已从笔尖解冻。您还无法确定应用程序委托是否已收到 UIApplicationDidFinishLaunchingNotification 通知。

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

最好让应用程序委托在“良好且准备就绪”时在上下文中传递,最好是在 applicationDidFinishLaunching: 方法中。

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

收集有关 iPhone 应用程序生命周期的更好解释。

希望有帮助。


更多更新:

对 iPhone 发布顺序的深入讨论:
http://www.bit-101.com/blog/?p=2159< /a>

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文