在不损害应用程序性能的情况下,从Core Data执行级联删除对象的有效方法是什么?

时间:2012-07-24 02:58:13

标签: ios core-data nsmanagedobjectcontext

我们的应用程序中的数据库由嵌套了几层深层的对象组成。出于体系结构的原因,我们现在不可能远离这一点。

大部分数据每天都会过期。随着数据库规模的扩大,我们的应用程序性能会下降。

因此,我们需要找到一种有效的方法来保持数据库的小型化(至少在本版本中),我们正在考虑采用以下方法之一:

  1. 在applicationWillResignActive期间,通过迭代根级别的所有对象来删除NSManagedObjects,在每个对象上调用delete,然后允许将删除级联到3层“to-many”对象。这涉及一个上下文保存,将所有这些提交给DB。 这通常需要10-20秒(在iPhone 4上)才能删除对象,而Springboard会在10秒后终止进程。这样做的一个主要缺点是,如果上下文保存在10秒超时之前没有完成,则每次用户运行应用程序时都不会删除任何内容并且数据库会继续增长。

  2. 删除didFinishLaunchingWithOptions或applicationDidBecomeActive中的整个sqlite文件,或者删除applicationWillResignActive中的整个sqlite文件。这会强制我们弹出应用程序视图控制器堆栈的根目录,以避免尝试显示已删除的数据。最大的缺点是应用程序必须下载并解析数据几秒钟,然后用户才能在下次启动应用程序时执行任何操作。

  3. 在用户点击“主页”或“电源”按钮后,使用beginBackgroundTaskWithExpirationHandler删除数据库对象。与此相关的未知因素使其变得可怕。有人这样做(成功)吗?

  4. 在应用运行时以增量方式删除较小的对象组。这会增加设备的负载,从而破坏了tableviews的平滑性,使它们感到紧张。在删除旧对象时,API调用已经解析的数据量似乎不切实际。

  5. 对于删除核心数据中对象的最佳做法的任何想法都将不胜感激!

3 个答案:

答案 0 :(得分:1)

我遇到了这种情况,我没有时间清理数据。

我解决了将一些关键实体标记为已删除(实体属性),并在以后删除它们(和级联)的问题。您不必标记每个已删除的实体,只需标记允许推迟删除的实体,因此UI可以轻松地知道是否要删除任何标记或未标记的实体。听起来很难,但如果您的数据模型足够干净,那就不应该了。

当您的应用重新启动时,您要么删除实体并进行级联 - 如果这不能结束,您只需在可能的情况下重新启动删除 - 或者首先迭代并标记所有可删除的实体,可能会删除它们“逐一”。这可以在后台完成而不会弄乱UI(因为UI知道可删除的实体)。如果您遇到性能问题,可以非常轻松地逐步处理删除。

“以后标记和删除”政策对我来说效果很好。

答案 1 :(得分:1)

orange80,

您应该在-applicationDidEnterBackground中启动的后台队列中进行级联删除:要防止被终止,您必须使用后台任务ID。

我在经常使用的实例CD应用程序中使用此策略。总的来说,使用这种策略,用户永远不会看到删除。

安德鲁

答案 2 :(得分:0)

您可能需要考虑将选项1与标记某些实体进行删除相结合。这样,即使删除没有在应用程序退出时完成,在启动时(假设您的应用程序启动还没有花费一些时间),您可以执行已标记实体的删除(比如几秒钟)然后诉诸“轻松” “在后台删除,例如没有用户交互时(没有移动表视图)。当然,这会增加一些时间来启动应用程序,但我认为根据您的具体情况,这可能是一个可行的选择。

此外,我希望您通过Core Data执行批量加载,并且只根据需要将对象加载到内存中。

快速重新阅读您的问题我只是想到了另一个想法......排在第2行......为什么不尝试将过时的数据迁移到单独的文件,然后当用户退出应用时,只需删除那个文件?迁移这些对象肯定会有开销,但它可以提供更顺畅的用户体验。