我运用 Core Data 现已有三年的时刻了,虽然至今也不能算是彻底把握,但基本上能够做到熟练运用,很少会犯原则性的错误了。当时,怎么让 Core Data 融入流行的运用架构体系,在 SwiftUI、TCA、Unit Tests、Preview 等环境下更加顺畅地作业已成为我的主要困扰和研究方向。我将经过几篇文章来介绍近半年来在这方面的一些主意、收获、体会及实践,也期望能够与有相似困惑的朋友进行更多的探讨。

原文宣布在我的博客wwww.fatbobman.com

欢迎订阅我的公共号:【肘子的Swift记事本】

廉颇老矣 尚能饭否?

Core Data 是一个具有悠长前史的结构。假如仅从苹果在 2005 年发布 MacOS X Tigger 中第一次集成了 Core Data 结构算起,Core Data 至今只需十余年的时刻,但考虑到其很大一部分规划都承继自 Next 于 1994 年推出的 EOF( Enterprise Objects Framework )结构,如此算来,其中心规划理念现已诞生了接近三十年。在 Core Data 结构的代码中,至今仍到处充满着具有前史感的 NS 前缀。

与当时 Core Data 主流的运用场景不同,EOF 被集成在运用程序服务器 WebObjects 中,在电子商务的前期,招引了不少大公司的运用,客户包括 BBC、Dell、Disney、GE、Merrill Lynch 等。直到前些年,WebObjects 仍为苹果的 Apple Store 和 iTunes Store 供给动力。如此,便不难理解为什么与其他流行的移动耐久化计划不同,Core Data 并不过火寻求数据的访问功率,稳定才是其最重视的点,这在很多开发者中早已 形成共识。

或许是规划理念非常超前并且完成得现已足够完美( 低情商:近些年苹果投入度较低 ),最近五六年中,苹果在不需求对中心代码做太多调整的情况下,便为 Core Data 增加了如下的新功用:

  • NSPersistentContainer

    和谐器、耐久化存储、保管上下文包装的官方完成。简直无需调整任何中心代码。

  • 耐久化前史盯梢

    近期最大的改动。在耐久化存储上增加了更多 Triger 的操作,并在和谐器上供给了响应变化的 API

  • 数据的批量操作

    答应开发者跳过上下文,直接从和谐器上对耐久化存储进行批量操作

  • Core Data with CloudKit

    简直不需对中心代码做调整,新增了 NSPersistentCloudKitContainer ,在和谐器上附加了一个用于网络同步的模块。

  • async/await 支撑

    供给了新的 perform 办法的完成

虽然开发者中近期流传着( 或幻想着 )苹果会推出全新的结构取代 Core Data 的言论,但只需仔细了解并研究 Core Data 的前史和代码便能够剖析出新结构呈现的可能性非常的低。一方面,其优异的架构规划仍可满足未来增加新功用的需求;另一方面,替换一个具有如此悠长前史且以稳定性著称的结构需求极大的勇气。因而,开发者可能会在未来很长的一段时刻中继续运用这套结构。

严格来说,排除掉不易学、不好把握这个缺点,在一个抱负的环境中,Core Data 不管从稳定性、开发功率、可扩展性等方面来说都相当的优异( 网络同步不稳定不是 Core Data 的问题 ),在管理方针图、方针生命周期以及数据耐久化方面仍是苹果生态的最佳挑选。

不过这并非意味着 Core Data 能够彻底适应如今的开发环境。虽然它依然具有超前的头脑、强壮的内脏,但表面实在太陈旧了,已很难与新结构和新的开发流程匹配。假如咱们能够为它创立一个新的表面,或许能够让它重焕青春,再战十年。

你的荣耀,我的烦恼

有趣的是,形成 Core Data 与新结构、新开发流程不和谐的大多因素都是 Core Data 引以为傲的一些特色或优势。

数据结构谁做主

Core Data 的中心是方针图管理,耐久化功用只是其一个顺便功用。相较于其他结构,Core Data 对联系的描绘和处理才能是其中心竞争力。或许是为了便于描绘复杂的联系逻辑,开发者在创立数据结构前,通常需求在 Xcode 的数据模型编辑器中创立实体描绘( 支撑运用代码直接来界说,但较少会选用此种方法 ),然后运用主动或手动的方法生成对应的 NSManagedObject 界说代码。如此一来会呈现如下问题:

  • 为了坚持与 Objectiv-C 的兼容性( Core Data 的内部数据仍选用 Objective-C 完成 ),开发者在数据模型编辑器中,仅能用有限的数据类型来描绘特点。这使得开发者在界说一个新的数据结构( 对应 Core Data 的实体 )时,无法在第一时刻用最适合 Swift 语言风格的方法进行考虑和描绘,不自觉地便受制于模型编辑器的表述才能。
  • 在运用了数据网络同步的情况下( Core Data with CloudKit),因为无法在产品上线后修正实体或特点称号( 只增不减不改原则,不管原有的实体、特点、联系称号界说得多么不合理,开发者也只能承受。跟着版本的不断更迭,这些不合适的命名会充满在代码各处,让人欲哭无泪。
  • 很难在第一时刻进入业务流程的开发状态。当将保管方针作为数据描绘的类型后,开发者往往开始编写的代码都是有关于 Core Data Stack 方面的。在运用的开发过程中,对数据界说的任何调整都需求经过层层处理( 模型编辑器、对应的 NSManamgedObject 界说、Stack 中的相关代码 ),严重影响了开发的功率。

总而言之,一旦在运用中运用了 Core Data,开发者很难在开发的初始阶段摆脱它的阴影。从导入 Core Data 的那一刻起,便对开发者的创造力、直觉、热心产生了负面的影响。

R0 值超高的保管机制

Core Data 的保管机制自 EOF 时期便现已存在。该机制让 Core Data 将来自底层的数据源露出为耐久方针的保管图( 内存数据方针 ),并经过保管上下文对方针图进行修正和盯梢。保管机制供给的数据慵懒加载才能能够协助开发者在读取功率和内存占用之间取得平衡。能够说,具有保管机制是 Core Data 长期以来的一个引以为傲的特性。

但保管机制意味着,开发者在进行恣意操作前首要要搭建符合要求的保管环境。操作保管方针有必要首要创立保管方针上下文。而让上下文能够作业的前提是创立保管和谐器和耐久化存储。

除了创立保管环境所需操作繁杂外,保管环境在某些场合下的运行稳定性并不可靠。事实上,Core Data 的保管环境现已是当下导致 SwiftUI 预览失利的主要原因之一。别的,对保管环境的预备和重置也会拖慢 Unit Tests 的速度,影响开发者编写单元测试的意愿。由此一来,会严重打击开发者在运用中选用模块式( SPM )开发的积极性。

假如说奥密克戎 BA.4/5 的 R0 值为 18.6 ,那么保管机制对于运用中触及保管方针的代码的基本繁殖数便是 ∞ ,一旦沾上便甩不掉。

线程绑定与 Sendable

虽然 Core Data 的保管方针并非线程安全的,但只需严格遵守运用约好( 只在创立保管方针的保管上下文中运用 ),在 Core Data 中进行多线程开发是很安全的。虽然有些开发者以为在 Core Data 中进行多线程有些烦琐,但又不得不供认相较于其他相似的结构,运用 Core Data 进行多线程开发,稳定性是很有保障的。

跟着 Swift 5.5 在异步和并发方面才能的提升,开发者会自觉不自觉的在代码中运用到新的异步或并发机制。例如,TCA 的 Reducer 目前正朝 Global Actor 方向演进( 也便是 Reducer 将不再运行于主线程上 )。为了防止呈现线程安全问题,让数据符合 Sendable 协议是有效的手法。

很显然,保管方针并不具备符合 Sendable 协议的基础。怎么让 Core Data 与运用新并行机制的结构进行合作,同样是摆在开发者面前的一个新课题。

我向往的运用方法

虽然有些贪心,但我仍期望能做到鱼和熊掌兼而得之。咱们将经过几篇文章一起来探讨,试图完成如下方针:

  • 将 Core Data 对数据界说过程中( 尤其是开发的初期 ) 的影响降至最低
  • 将数据源切换至 Core Data 后,无需修正当时的代码
  • 在预览、单元测试阶段不再受保管环境的困扰,可便利对代码实行模块化管理
  • 仍保留 Core Data 的数据慵懒加载机制,防止形成内存的过多占用
  • 兼容新的并行机制,找寻 Senable 的最大公约数
  • 用最少的代码完成上述方针,防止增加系统的不稳定性

下文介绍

鄙人篇文章中,咱们将首要从数据( 对应 Core Data 的实体、特点 )的界说谈起,测验经过泛型、类型擦除等方法从界说中移除保管环境。

因为一直没有为这个系列的文章想好恰当的标题,便暂且临时选用了 “SwiftUI 与 Core Data” 这个称号。假如你有什么好的建议欢迎告诉我。

期望本文能够对你有所协助。同时也欢迎你经过 Twitter、 Discord 频道 或博客的留言板与我进行交流。

订阅下方的 邮件列表,能够及时取得每周的 Tips 汇总。

原文宣布在我的博客wwww.fatbobman.com

欢迎订阅我的公共号:【肘子的Swift记事本】