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