变幻莫测:CoreData 中 Transformable 类型面面俱到(八)
概述
各位似秃似不秃小码农们都知道,在苹果众多开发平台中 CoreData 无疑是那个最简洁、拥有“官方认证”且最具兼容性的数据库框架。使用它可以让我们非常方便的搭建出 App 所需要的持久存储体系。
不过,大家是否知道在 CoreData 中还存在一个 Transformable 类型,它到底是个啥?应用场景有哪些?在最新的 SwiftData 中有没有对应物?对于开发者又有哪些“见雀张罗”的撸码陷阱和最佳实践呢?
在本篇博文中,您将学到如下内容:
- 概述
- 7. Transformable 和 Binary Data 类型的区别
- 7.1 相同之处
- 7.2 核心区别
- 7.3 选择建议
- 8. SwiftData 中有 Transformable 类型吗?
- 8.1 为什么 SwiftData 没有 `Transformable` 类型?
- 8.2 SwiftData 中处理 `Transformable` 场景的两种方式
- 8.2.1 方法 1:直接使用 `Codable` 类型
- 8.2.2 方法 2:手动处理二进制数据(类似 `Binary Data`)
- 8.3 关键对比:CoreData vs SwiftData
- 8.4 迁移 CoreData `Transformable` 到 SwiftData
- 总结
本系列文章一共包括将近 3w 枚机智而幽默的文字、详实的大段代码示例以及海量图片,定能让小伙伴们对 Transformable 类型的“驾驭”更加胸有成竹、胜券在握!
那还等什么呢?让我们马上开始 Transformable 大冒险吧!
Let’s go!!!😉
7. Transformable 和 Binary Data 类型的区别
经过前面几篇文章的讨论,相信大家都对 Transformable 类型有了相当的了解。
熟悉 CoreData 的小伙伴们都知道,除了 Transformable 以外,对于托管类型的字段来说还有另一种 Binary Data 类型,它也可以被用来存储具体的数据。那么它和 Transformable 类型又有什么异同呢?
在 CoreData 中,Transformable 和 Binary Data 是两种不同的数据类型,它们的核心区别在于 数据存储方式 和 使用场景,但也有一些相似之处。
接下来,就让我们娓娓道来吧。
7.1 相同之处
特性 | Transformable & Binary Data |
---|---|
存储形式 | 最终都以二进制形式(BLOB)存储在 SQLite 中(或其他持久化存储) |
灵活性 | 都可存储非结构化数据(如自定义对象、二进制流等) |
内存映射 | 数据在加载到内存前不会完全解包,适合处理大文件或懒加载场景 |
7.2 核心区别
特性 | Transformable | Binary Data |
---|---|---|
数据类型 | 存储 自定义对象(如 struct 、class 实例等) | 存储原始 二进制数据(如 NSData 、Data ) |
序列化/反序列化 | 自动转换:通过 NSValueTransformer 将对象序列化为 NSData ,反之亦然 | 手动处理:直接操作二进制数据,需自行解析内容(如解码为图片、字符串等) |
使用场景 | 适合存储 结构化自定义数据(如 UIColor 、自定义配置类、复杂模型等) | 适合存储 原始二进制数据(如文件、图片、加密数据、未格式化的字节流等) |
代码侵入性 | 需要实现 NSSecureCoding 协议或自定义 NSValueTransformer | 无需额外代码,直接操作 Data 对象 |
数据版本兼容性 | 如果对象结构变化(如新增属性),需处理数据迁移 | 数据格式变化时,需自行处理兼容性(如更新解析逻辑) |
安全性 | 使用 NSSecureUnarchiveFromDataTransformer 可防止恶意数据注入(iOS 12+ 推荐) | 需自行验证二进制数据的合法性 |
7.3 选择建议
场景 | 推荐类型 | 理由 |
---|---|---|
存储自定义对象(需结构化序列化) | Transformable | 自动处理对象与二进制数据的转换,代码更简洁 |
存储原始二进制流(如文件、图片) | Binary Data | 直接操作 Data ,无需序列化开销 |
需要跨平台兼容性 | Binary Data | 避免依赖特定平台的序列化实现(如 NSSecureCoding ) |
数据安全性要求高 | Transformable | 使用 NSSecureUnarchiveFromDataTransformer 防止恶意数据反序列化 |
最后,再简单说一下适配 Transformable 和 Binary Data 需要注意的地方:
- Transformable 的开销:序列化/反序列化过程会增加 CPU 和内存消耗,不适合频繁读写大的数据。
- Binary Data 的优化:对于大文件(如图片、视频),建议启用 Allows External Storage 选项,让 CoreData 自动决定是否将数据存储在独立外部文件中。
通过合理选择 Transformable
或 Binary Data
类型,我们可以高效管理 CoreData 中的复杂数据,同时平衡开发效率与性能。
那么,大家现在对它们的优缺点和应用场景是不是了然于胸了呢?
8. SwiftData 中有 Transformable 类型吗?
最后一个问题是,在苹果最新的 SwiftData 框架中有没有类似 Transformable 的类型呢?
其实,在 SwiftData 中 Transformable
类型的概念并没有直接出现,但这并不意味着无法处理原本需要 Transformable
的场景。SwiftData 通过更现代化的设计模式和 Swift 原生特性(如 Codable
协议和类型安全),提供了更简洁的解决方案。
下面,我们就对此来详细分析一番吧!
8.1 为什么 SwiftData 没有 Transformable
类型?
-
设计哲学差异:
- CoreData 的
Transformable
是为了兼容 Objective-C 时代的NSCoding
协议,需要手动管理序列化和反序列化。 - SwiftData 基于 Swift 的原生类型系统,鼓励直接使用
Codable
协议和 Swift 原生类型,减少样板代码。
- CoreData 的
-
类型安全优先:
- SwiftData 通过
@Model
宏和 Swift 类型推断,直接支持复杂类型的存储,无需显式声明Transformable
。 - 核心思想是 “只要我们的类型可以表示为 Swift 原生类型或遵循
Codable
,就可以直接存储”。
- SwiftData 通过
8.2 SwiftData 中处理 Transformable
场景的两种方式
8.2.1 方法 1:直接使用 Codable
类型
如果自定义类型遵循 Codable
协议,SwiftData 会自动将其序列化为二进制数据存储(类似 Transformable
的底层行为)。
示例:存储自定义 AppConfig
对象:
// 1. 定义自定义类型并遵循 Codable
struct AppConfig: Codable {var smartVer: Intvar fontSize: CGFloat
}// 2. 在 SwiftData 模型中直接使用该类型
@Model
class Settings {var config: AppConfig // SwiftData 自动处理序列化init(config: AppConfig) {self.config = config}
}
8.2.2 方法 2:手动处理二进制数据(类似 Binary Data
)
对于非 Codable
类型或需要完全控制序列化逻辑的场景,可以手动转换为 Data
存储。
示例:存储 UIColor
:
@Model
class Settings {// 将颜色存储为 Dataprivate var colorData: Data// 通过计算属性访问 UIColorvar themeColor: UIColor {get {return try! NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: colorData) ?? .systemBlue}set {colorData = try! NSKeyedArchiver.archivedData(withRootObject: newValue, requiringSecureCoding: true)}}init(themeColor: UIColor) {self.colorData = try! NSKeyedArchiver.archivedData(withRootObject: themeColor, requiringSecureCoding: true)}
}
8.3 关键对比:CoreData vs SwiftData
场景 | CoreData 实现 | SwiftData 实现 |
---|---|---|
存储自定义对象 | 使用 Transformable + NSCoding | 直接使用 Codable 类型 |
存储非 Codable 对象 | 自定义 NSValueTransformer | 手动转换为 Data 存储,通过计算属性封装访问逻辑 |
代码复杂度 | 需手动实现序列化/反序列化 | 利用 Swift 原生特性(如 Codable )减少代码 |
类型安全性 | 依赖运行时类型检查 | 编译时类型安全 |
8.4 迁移 CoreData Transformable
到 SwiftData
-
简单迁移:
- 如果原 CoreData 的
Transformable
类型已遵循Codable
,可以直接替换为 SwiftData 中的对应类型。
- 如果原 CoreData 的
-
复杂迁移:
- 对于依赖
NSCoding
的旧类型,在 SwiftData 中重构为Codable
类型,或使用手动Data
转换。
- 对于依赖
综上所述,SwiftData 通过拥抱 Swift 原生特性(如 Codable
)和编译时类型安全,简化了原本需要 Transformable
的场景。开发者可以:
- 直接存储
Codable
类型:无需额外配置,SwiftData 自动处理序列化。 - 手动管理二进制数据:通过
Data
属性和计算属性的封装,灵活把控非标准类型。
这种设计既保留了灵活性,又大幅减少了模板代码,更符合现代 Swift 开发范式,就问小伙伴们赞不赞呢?
到这里,我们已经对 CoreData 中的 Transformable 类型有了全面而详细的理解和实践,一路走来不易,感谢大家的观看和学习!
小伙伴们不妨给自己点一个大大的赞吧!棒棒哒!💯
总结
在本篇博文中,我们先是介绍了 Transformable 和 Binary Data 类型的异同,并随后讨论了 Transformable 对应物在 SwiftData 中的实现。
感谢观赏,再会啦!😎