MOCloner

中文版说明

MOCloner 是一个小型库,旨在实现 NSManagedObject 的可定制深度拷贝。支持一对一、一对多、多对多关系。除了忠实于原始数据的拷贝方法外,它还提供了诸如选择性拷贝和在拷贝过程中生成新值等功能。

实现原理

通过 NSAttributeDescription、NSRelationshipDescription 遍历 NSMangedObject 的属性和关系,并通过 userinfo 设置深度拷贝参数。

更多实现细节,请参考 如何在 Core Data 中对 NSManagedObject 进行深拷贝

深度拷贝规则

拷贝一对一和一对多关系下的所有数据。

当遇到反向关系为 to-many 的 Entity 时,停止该 Entity 下分支的复制,并将新复制的对象添加到该 Entity 中。

rules

基本示例

创建上图中的 Note 的深度拷贝

let cloneNote = try! MOCloner().clone(object: note) as! Note

从关系链的中间部分向下进行深度拷贝(不拷贝关系链的向上部分)

// Add the exclude relationship names to the excludedRelationshipNames
let cloneItem = try! MOCloner().clone(object: item, excludedRelationshipNames: ["note"]) as! Item

自定义

MOCloner 通过在 Xcode 的 Data Model Editor 中向 User Info 添加键来定制深度拷贝过程。目前支持以下命令:

image-20211112200648882

image-20211112201348978

image-20211112205856380

image-20211112210330127

如果以上 userinfo 键名与您的项目中已使用的键名冲突,您可以通过自定义 MOClonerUserInfoKeyConfig 重置它。

let moConfig = MOCloner.MOClonerUserInfoKeyConfig(
    rebuild: "newRebuild", // new Key Name
    followParent: "followParent",
    withoutParent: "withoutParent",
    exclude: "exclude"
)

let cloneNote = try cloner.cloneNSMangedObject(note,config: moConfig) as! Note

系统要求

MOCloner 的最低要求是 macOS 10.13、iOS 11、tvOS 11、watchOS 4 及以上版本。

安装

MOCloner 使用 Swift Package Manager 进行分发。要在另一个 Swift 包中使用它,请将其作为依赖项添加到您的 Package.swift 中。

let package = Package(
    ...
    dependencies: [
        .package(url: "https://github.com/fatbobman/MOCloner.git", from: "0.1.0")
    ],
    ...
)

如果想在您的应用程序中使用 MOCloner,请使用 Xcode 的 File > Add Packages... 将其添加到您的项目中。

import MOCloner

由于 MOCloner 只有几百行代码,您可以将代码复制到您的项目中并直接使用。

注意事项

在私有上下文中进行深度拷贝

当深度拷贝涉及大量数据时,请在私有上下文中操作,以避免占用主线程。

最好在深度拷贝操作前后使用 NSManagedObjectID 进行数据传输。

内存

当托管对象的深度拷贝涉及大量关系数据时,可能会导致大量内存使用。当它包含二进制数据(例如在 SQLite 中存储大量图像数据)时,这一点尤其明显。您可以考虑以下方法来控制内存使用:

许可和支持

MOCloner 使用 MIT 许可,您可以自由地在您的项目中使用它。但请注意,MOCloner 不提供任何官方支持渠道。

Core Data 提供了丰富的功能和选项,开发者可以使用它们来创建大量的不同关系图组合。MOCloner 仅针对其中一些情况进行了测试。因此,在开始准备将 MOCloner 用于您的项目之前,强烈建议您花一些时间熟悉其实现,并进行更多的单元测试,以防您遇到任何可能的数据错误问题。

如果您发现问题、错误,或想提出改进建议,请创建 IssuesPull Request