Core Data 管理对象上下文设计建议

2024-02-13

我们正在开发一个企业级应用程序,它将使用核心数据存储数以万计的对象,但我们在多个方面都遇到了问题。


我们的应用程序有几个独立的系统,可以在需要时对数据进行操作。这些系统包括项目的发现、项目的加载、同步和UI显示。如果我们正确地设计我们的软件,那么由于不同的系统修改相同的对象而导致的合并冲突应该很少甚至没有。每个系统都有自己的操作队列,全部在后台执行。我们希望将所有对象创建和修改保留在后台,以最大程度地减少 UI 性能问题,尤其是在初始启动期间,可能会根据服务器上的数据创建数千个对象。在这里,我们的各种设计尝试遇到了一些问题。在这些启动过程中会消耗大量内存,并且所有上下文和子上下文的编排不正确,从而导致死锁和崩溃。 我们尝试了以下设计:

  • 一根NSPrivateQueueConcurrencyType有一个子对象的托管对象上下文NSMainQueueConcurrencyType语境。 UI 获取结果控制器使用此子上下文来获取结果。来自NSMainQueueConcurrencyType子上下文,我们创建了一个NSPrivateQueueConcurrencyType子上下文,我们称之为“ savingContext”,每个后台操作都会创建该“ savingContext”的子上下文,进行更改,最后执行我们所谓的“深度保存”,递归地保存到顶部。我们最初选择这种设计是为了不必处理NSManagedObjectContextDidSaveNotification来自许多不同子上下文的通知。我们结束了对NSPrivateQueueConcurrencyType上下文和对对象的访问performBlockAndWait:。从功能上来说,这个设计是有效的。所有更改和插入都保存到持久存储中,并且 UI 随更改而更新。这引入了两个问题。其中之一是在启动过程中用户界面滞后,因为合并的更改经过NSMainQueueConcurrencyType子上下文,更重要的是,在启动期间内存使用率非常高。由于无法调用,我们会遇到过高的 RAM 使用量reset在上下文中递归(因为主 UI 子上下文也在那里)和/或缺乏何时调用的知识refreshObject:mergeChanges:。于是我们走了一条不同的路。
  • 有两个与持久存储协调器链接的顶级上下文,一个NSPrivateQueueConcurrencyType用于保存子上下文,以及NSMainQueueConcurrencyType用于UI显示。这NSMainQueueConcurrencyTypeNSManagedObjectContextDidSaveNotification来自主站的通知NSPrivateQueueConcurrencyTypecontext 并将它们合并到主线程中。每个后台操作都会创建一个主上下文的子上下文NSPrivateQueueConcurrencyTypecontext,也具有私有队列并发类型,执行它的操作,递归地执行“深度保存”,即对当前上下文执行保存,对其父级执行深度保存的递归调用,对当前上下文调用重置并再次保存。这样我们就可以避免内存问题,因为创建的对象在保存后会快速释放。然而,通过这种设计,我们遇到了很多问题,例如死锁、NSInternalInconsistencyException异常和获取的结果控制器不更新 UI,尽管有保存通知NSMainQueueConcurrencyType语境。这也会导致 UI 中的初始加载时间显着减慢。在之前的设计中,获取结果控制器返回结果的速度非常快,而这会导致 UI 阻塞几秒钟,直到视图加载(我们在中初始化获取结果控制器)viewDidLoad).

我们尝试了许多中间设计,但它们都围绕着相同的问题,要么非常高的内存使用率,获取的结果控制器不更新 UI 或死锁,NSInternalInconsistencyException例外情况。


我真的很沮丧。我忍不住觉得我们的设计对于一些本应相当简单的东西来说过于复杂,而正是我们缺乏对一些基本原理的理解才导致了我们的死亡。


那么你们有什么建议呢?对于我们的环境,您会推荐什么安排?我们应该如何管理不同线程中的不同上下文?释放插入对象和重置上下文的最佳实践?避免死锁?此时,我们将不胜感激所有帮助。


我还看到了 MagicalRecords 类别的推荐。推荐吗?我们已经投资使用核心数据类型,那么使用 MR 进行迁移有多困难?


首先,为了管理内存,第二种架构为您提供了更大的灵活性。

其次,有两种内存需要管理:malloc 内存和常驻 VM 内存。您可以拥有较低的 malloc 内存占用量,但仍然拥有较大的 VM 驻留区域。根据我的经验,这是由于 Core Data 积极保留新插入的项目。我通过保存后修剪通知解决了这个问题。

第三,MOC 价格便宜。使用它们并扔掉它们。换句话说,尽早且经常释放内存。

第四,尝试在主 MOC 上几乎不做任何数据库方面的事情。是的,这听起来适得其反。我的意思是,所有复杂的查询实际上都应该在后台线程上完成,然后将结果传递到主线程,或者在利用现在填充的行缓存的同时从主线程重做查询。通过这样做,您可以保持 UI 的活力。

第五,在我的多队列应用程序中,我尝试让所有保存真正发生在后台。这使我的主要 MOC 保持快速并与来自网络的数据保持一致。

第六,NSFetchedResultsController 是一个非常有用但专门的控制器。如果您的应用程序将其推到其权限范围之外,它就会开始锁定您的界面。当发生这种情况时,我会通过自己监听 -didSave 通知来滚动自己的控制器。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Core Data 管理对象上下文设计建议 的相关文章

  • 在 UITableView 的部分标题文本下方添加一些边距

    我已经设计了标题文本的样式 func tableView tableView UITableView cellForRowAtIndexPath indexPath NSIndexPath gt UITableViewCell let ce
  • cordova插件条码扫描仪打不开扫描

    我的条形码扫描仪插件有问题 我不是天才 我不太了解如何编写网络应用程序 我使用phonegap和cordova 并且尝试制作一个网络应用程序 在单击链接后扫描条形码 我之前已经使用此命令行安装了该插件 cordova plugin add
  • 下载进度条在 iOS 企业发行版中没有改变进度

    我正在通过企业分发开发和分发 iPad 应用程序 它们下载并执行良好 因此一切正常 Web 链接 ipa 文件 plist 文件 配置 问题 是 当用户单击链接进行下载时 iPad 中显示下载进度的进度条显示 正在等待 但却是空的并且永远不
  • java中使用多线程调用同一类的不同方法

    我有一个类 如下所示 具有三种方法 public class MyRunnable implements Runnable Override public void run what code need to write here to c
  • 如何在Spring-Boot中创建DefaultMessageListenerContainer?

    我是 Spring Boot 的新手 并尝试创建 DefaultMessageListenerContainer 以便我可以使用 weblogic workmanager 并以多线程方式运行多个消息侦听器 有人可以提供一些例子吗 到目前为止
  • NSUserDefaults 多久同步一次?

    的文档NSUserDefaults说synchronise方法被定期调用 但没有提及频率 10分钟的谷歌搜索没有发现任何信息 发生的频率是多少synchronise方法调用 这是一个未公开的实现细节 可能甚至不是一个恒定的时间间隔 但是 您
  • 在故事板中将 UITableView 的 rowHeight 设置为 UITableViewAutomaticDimension ?

    在 Xcode 6 中创建 iOS 8 应用程序时 如何设置 UITableViewrowHeight to UITableViewAutomaticDimension In WWDC 2014 第 226 场会议 表和集合视图中的新增功能
  • 如何在 Firebase Analytics 事件中报告参数

    我用过Fabric with iOS在此之前 在同一分析事件中报告自定义参数非常容易 如下所示 Answers logCustomEvent withName saved border customAttributes image inde
  • ReactNative - 未处理的 JS 异常:SyntaxError

    当我尝试在 iOS 8 上启动 RUN 应用程序时 出现这个奇怪的错误 Unhandled JS Exception SyntaxError仅此而已 不再有更多信息 有any1偶然发现这个问题吗 在 iOs 9 上应用程序运行正常 x代码版
  • 如何检测并找出程序是否陷入死锁?

    这是一道面试题 如何检测并确定程序是否陷入死锁 是否有一些工具可用于在 Linux Unix 系统上执行此操作 我的想法 如果程序没有任何进展并且其状态为运行 则为死锁 但是 其他原因也可能导致此问题 开源工具有valgrind halgr
  • 使 iOS 应用程序与 iPhone 6 和 iPhone 6 尺寸兼容 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我创建了一个应用程序 其中使用 xib 进行布局 目前我使用两种不同的 xib 一种用于iPhone4 320 480 一种用于iPh
  • HTML 分页

    有没有html分页的开源项目 我正在为 iPhone 开发一个应用程序 我想在 UIWebView 上显示 HTML 文件 并且不希望用户向下滚动以查看屏幕上未显示的剩余内容 我想在第二个 UIWebView 上显示剩余的内容 我怎样才能做
  • 这是 C# 的有效、惰性、线程安全的 Singleton 实现吗?

    我实现了这样的单例模式 public sealed class MyClass public static MyClass Instance get return SingletonHolder instance static class
  • 为 iOS 应用程序加载基于 SVG 的图像资源

    我从 thenounproject 购买了一个图标作为 SVG 图像 然后我使用一个名为的 macOS 程序Gapplin http gapplin wolfrosch com 将此 SVG 导出为 PNG 图像 它显示为 100x100
  • 以编程方式从底部裁剪图像

    我正在开发自定义相机应用程序 一切进展顺利 但我在从底部裁剪图像时遇到了问题 即 裁剪后的图像与原始图像具有完全相同的宽度 但高度将为原始图像的 1 3 并且必须从底部开始 斯威夫特3解决方案 func cropBottomImage im
  • UITableView 滑动删除 iOS 上的手势冲突

    我的手势识别器有问题 我的目标是在表视图中实现使用滑动删除 但我认为其他手势是相互冲突的 我正在使用这个库romonthego REFrostedViewController https github com romaonthego REF
  • 为什么 Web Worker 性能在 30 秒后急剧下降?

    我正在尝试提高在网络工作人员中执行时脚本的性能 它旨在解析浏览器中的大型文本文件而不会崩溃 一切都运行得很好 但我注意到使用网络工作者时大文件的性能存在严重差异 于是我做了一个简单的实验 我在同一输入上运行脚本两次 第一次运行在页面的主线程
  • 如何重新启动死线程? [复制]

    这个问题在这里已经有答案了 有哪些不同的可能性可以带来死线程回到可运行状态 如果您查看线程生命周期图像 就会发现一旦线程终止 您就无法返回到新位置 So 没有办法将死线程恢复到可运行状态 相反 您应该创建一个新的 Thread 实例
  • 如何将相机中的图像保存到 iPhone 图库中的特定文件夹?

    嘿 我是 iPhone 新手 最近我一直在尝试制作一个应用程序 基本上 我想要做的是 如果用户将从相机捕获任何图像 那么它应该保存在设备库中 我知道如何将照片保存在图库中 它对我有用 但我无法将所有捕获的图像保存到设备图库中的特定文件夹 例
  • .NET UI 元素线程限制的原因

    我们知道 除了实例化元素的线程之外 不可能从任何线程执行操作任何 UI 元素属性的代码 我的问题是 为什么 我记得当我们使用 COM 用户界面元素时 在 COM Visual Basic 6 0 时代 所有 UI 元素都是使用 COM 类和

随机推荐