如何在应用程序退出时正确删除“临时”NSManagedObject

Posted

技术标签:

【中文标题】如何在应用程序退出时正确删除“临时”NSManagedObject【英文标题】:How to properly delete a "temporary" NSManagedObject upon the application quitting 【发布时间】:2011-02-26 20:01:30 【问题描述】:

我创建了一个临时的 NSManagedObject 并将它与主 NSManagedObjectContext 相关联。我需要能够在上下文中将其视为功能齐全的对象(执行获取请求等),因此在没有关联上下文的情况下无法创建它。我在 ViewWillDisappear 中包含删除托管对象的逻辑,条件是新视图控制器不只是被推入堆栈:

- (void)viewWillDisappear:(BOOL)animated  
  [super viewWillDisappear:animated];

  NSArray *viewControllers = self.navigationController.viewControllers;
  if (viewControllers.count > 1 && [viewControllers objectAtIndex:viewControllers.count-2] == self) 
    // View is disappearing because a new view controller was pushed onto the stack
   else  
    // View is disappearing for some other reason
    [self.community.managedObjectContext deleteObject:self.community];
  

除了应用程序退出之外,这似乎在所有情况下都能正确删除托管对象。我尝试删除 viewDidUnload 中的对象,但似乎在应用程序退出时未调用该方法。我考虑过创建第二个托管对象上下文,但如果可能的话希望避免主要开销。

谢谢, 格雷厄姆

【问题讨论】:

为什么 NSManagedObjectContext -reset 不足以达到这个目的? 【参考方案1】:

将托管对象作为类变量保存在共享实例中,以便可以从应用程序中的更多位置访问它,而不是从您处理它的类。

有两种情况:

1) ios 4.0 之前 当 applicationWillTerminate 你可以从上下文中删除对象。

2) 从 iOS 4.0 开始。 当您的应用程序将进入后台并且您将终止进程时(使用“kill app bar”的艰难方式),applicationWillTerminate 将永远不会被调用。您无法识别此事件。所以你搞砸了 applicationWillTerminate。 您将不得不像这样解决它: - applicationWillEnterBackground: -> 将标识符保存到 userdefaults 或简单文件中的托管对象。 - applicationDidFinishLaunching: -> 如果文件存在,则删除它所引用的托管对象。 - applcationWillEnterForeground: -> 删除文件。

现在当您的应用程序进入后台并返回时,您将拥有相同的状态并且对象不会被删除。 当您杀死您的应用程序时,该对象将在启动时被删除。

【讨论】:

感谢 Mats - 逻辑就像一个魅力!我只想指出,我使用 applicationWillResignActive: 将对象的 URI 保存到 NSUserDefaults(我不相信 applicationWillEnterBackground: 方法存在)。如果您正在寻找有关如何将标识符保存到托管对象的详细信息,请查看此帖子 "Safely fetching an NSManagedObject by URI"。请注意,自从写了那篇文章以来,方法 existingObjectWithID:error: 已添加到 NSMangedObjectContext 好的,格雷厄姆。我想我的意思是 appliationDidEnterBackground。但是 willResign 也可以。祝你好运。【参考方案2】:

在您的应用委托中,实现 -applicationWillTerminate: 方法。此方法在您的应用程序从内存中清除之前调用,您可以在那里删除临时托管对象。

【讨论】:

【参考方案3】:

我知道您已经有了一个可行的答案,但是如果您的对象确实是临时的,并且永远不会被保存,为什么不在子上下文中创建它呢?它仍然具有您想要的所有获取可见性,但永远不会被推送到其他上下文,也不会保存在物理数据库中,直到您在上下文上调用 save。

如果你从不调用 save,临时对象将永远不会被保存,从而真正使其成为临时对象。

而且最重要的是......您根本不需要编写任何额外的代码或处理所有“退出”条件,因为它从未被放入实际的数据库中。

【讨论】:

【参考方案4】:

applicationWillTerminate 及其多任务表亲可以工作,但由于您只删除一个对象,因此最好的方法是在每次删除后保存您的上下文。

只需拨打- (BOOL)save:(NSError **)error

[self.community.managedObjectContext deleteObject:self.community];
NSError *error = nil;
[self.community.managedObjectContext save:&error];

【讨论】:

以上是关于如何在应用程序退出时正确删除“临时”NSManagedObject的主要内容,如果未能解决你的问题,请参考以下文章

退出并加载我的应用程序时,如何将图像保存并读取到临时文件夹

退出函数时删除临时表

MySQL如何删除#sql开头的临时表

退出时删除 QQuickView 会导致 Qt 应用程序冻结

Edge浏览器怎样设置退出时删除浏览历史记录?

如何使用 Asp.net 删除临时文件