Core Data入门:iOS数据持久化方案(零基础实战教程)
大家好,我是掘金上经常写入门教程的全栈工程师。今天我想和大家聊聊 Core Data —— 这是苹果官方提供的、面向 iOS/macOS 开发的数据持久化框架。
我当初学 iOS 开发的时候,面对“如何把用户输入的数据存下来”这个问题,一度非常困惑。NSUserDefaults?只能存小量配置;直接写文件?结构复杂又容易出错。后来接触到 Core Data,才发现:原来苹果早就为我们准备好了一套强大又易用的本地数据库方案!
这篇文章就是专门写给完全零基础的新手朋友的。你不需要懂数据库,也不需要会 SQL,只要会点 Swift 基础语法,就能跟着一步步做出一个能真正保存数据的 App。
💡 本文关键词:教程、资源
📌 目标:30 分钟内,亲手完成一个用 Core Data 存储“待办事项”的 Demo
一、Core Data 是什么?能做什么?
简单来说,Core Data 不是数据库,而是一个对象图管理框架,但它能帮你把数据持久化到磁盘上(通常是 SQLite 文件)。
你可以把它理解为:
- 一个“对象 ↔ 数据”的自动转换器
- 一个帮你管理数据生命周期的工具
- 一个无需写 SQL 就能操作本地数据的方案
典型应用场景:
- 用户设置(比如主题颜色、通知偏好)
- 聊天记录、笔记、待办事项
- 离线缓存的新闻/商品列表
✅ 优点:苹果原生支持、与 SwiftUI/UIKit 深度集成、类型安全、自动迁移能力
⚠️ 注意:它不是万能的!如果要做复杂查询或多表关联,可能 SQLite 或 Realm 更合适
二、环境准备:创建支持 Core Data 的项目
我们用 Xcode 创建一个最简单的项目来开始。
步骤 1:新建 Xcode 项目
- 打开 Xcode(建议 14.0 以上版本)
- 选择 App 模板 → 点击 Next
- 填写:
- Product Name:
TodoCoreData - Interface: SwiftUI(本文使用 SwiftUI,更简洁)
- Language: Swift
- ✅ 勾选 Use Core Data
- Product Name:
🔍 关键点:一定要勾选 “Use Core Data”!Xcode 会自动生成必要的配置文件和代码。
步骤 2:检查生成的文件
项目创建后,你会看到几个关键文件:
TodoCoreDataApp.swift:App 入口,已包含 Core Data 初始化代码PersistenceController.swift:核心!负责管理数据上下文(ManagedObjectContext)TodoCoreData.xcdatamodeld:数据模型文件(重点!后面要编辑它)
💡 避坑指南:如果你忘记勾选 Core Data,也可以手动添加,但对新手不友好。建议重新建项目。
三、核心概念:用大白话解释专业术语
在动手前,先搞懂这几个词(别怕,我会用生活例子解释):
| 术语 | 类比解释 | 技术定义 |
|---|---|---|
| Entity(实体) | 数据表(比如“学生表”) | 数据模型中的一个类,对应一种数据类型 |
| Attribute(属性) | 表的列(比如“姓名”、“年龄”) | 实体的一个字段,有类型(String、Int16 等) |
| ManagedObject(托管对象) | 表中的一行数据 | Entity 的实例,代表一条具体记录 |
| ManagedObjectContext(上下文) | 临时工作区 | 你在里面增删改查数据,最后统一保存到磁盘 |
🧠 我当初的理解误区:以为 Core Data = SQLite。其实它是更高层的抽象,你操作的是“对象”,不是“表”。
四、实战项目:做一个待办事项 App
我们将实现一个超简单的 Todo List:
- 输入任务内容
- 点击“添加”保存到 Core Data
- 列表实时显示所有任务
第一步:设计数据模型
- 在 Xcode 左侧点击
TodoCoreData.xcdatamodeld - 点击左下角 + 号 → Add Entity
- 将新 Entity 命名为
Task - 在右侧 Attributes 区域点击 + 添加属性:
- Name:
title,Type:String - Name:
isCompleted,Type:Boolean
- Name:
✅ 现在你的数据模型就定义好了:每条任务有“标题”和“完成状态”。
⚠️ 注意:修改模型后,如果之前运行过 App,需要删除模拟器 App 重新安装,否则会崩溃(进阶可用版本迁移,但新手先这样)
第二步:创建 Task 实体的 Swift 类(可选但推荐)
虽然 Xcode 能自动生成代码,但为了清晰,我们手动创建:
- File → New → File → Swift File
- 命名为
Task+CoreDataClass.swift - 输入以下代码:
import Foundation
import CoreData
@objc(Task)
public class Task: NSManagedObject {
}
- 再新建一个文件
Task+CoreDataProperties.swift:
import Foundation
import CoreData
extension Task {
@nonobjc public class func fetchRequest() -> NSFetchRequest<Task> {
return NSFetchRequest<Task>(entityName: "Task")
}
@NSManaged public var title: String?
@NSManaged public var isCompleted: Bool
}
🔍 说明:这两段代码告诉 Swift 如何与 Core Data 的
Task实体交互。Xcode 其实可以自动生成(在 .xcdatamodeld 文件中选择 Codegen → Class Definition),但手动写更可控。
第三步:编写 UI 与数据交互逻辑
打开 ContentView.swift,替换全部内容为:
import SwiftUI
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@FetchRequest(
sortDescriptors: [NSSortDescriptor(keyPath: \Task.title, ascending: true)],
animation: .default
)
private var tasks: FetchedResults<Task>
@State private var newTaskTitle = ""
var body: some View {
NavigationView {
VStack {
// 输入框 + 添加按钮
HStack {
TextField("输入任务...", text: $newTaskTitle)
.textFieldStyle(RoundedBorderTextFieldStyle())
Button("添加") {
addItem()
newTaskTitle = ""
}
.disabled(newTaskTitle.isEmpty)
}
.padding()
// 任务列表
List {
ForEach(tasks, id: \.self) { task in
Text(task.title ?? "无标题")
}
.onDelete(perform: deleteItems)
}
}
.navigationTitle("我的任务")
.toolbar {
ToolbarItem(placement: .navigationBarTrailing) {
EditButton()
}
}
}
}
private func addItem() {
withAnimation {
let newItem = Task(context: viewContext)
newItem.title = newTaskTitle
newItem.isCompleted = false
do {
try viewContext.save()
} catch {
print("保存失败: \(error)")
}
}
}
private func deleteItems(offsets: IndexSet) {
withAnimation {
offsets.map { tasks[$0] }.forEach(viewContext.delete)
do {
try viewContext.save()
} catch {
print("删除失败: \(error)")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
}
}
代码逐行解释:
@Environment(\.managedObjectContext):获取当前视图的数据操作上下文@FetchRequest:自动从 Core Data 获取Task列表,并按标题排序addItem():创建新 Task 对象 → 设置属性 → 调用viewContext.save()保存到磁盘deleteItems():通过上下文删除对象 → 再次 save()
✅ 关键点:所有增删改操作都必须调用
context.save()才会真正写入磁盘!
第四步:运行测试!
- 按 ▶️ 运行模拟器
- 在输入框输入“学习 Core Data”
- 点击“添加”
- 关闭 App 再重新打开 → 任务依然存在!
🎉 恭喜你!已经完成了第一个 Core Data 应用。
五、新手常见问题解答(FAQ)
Q1:为什么我改了数据模型,App 一启动就崩溃?
原因:Core Data 检测到模型版本变更,但没有做迁移。
解决方案(新手版):
- 删除模拟器上的 App(长按图标 → 删除)
- 重新运行项目
💡 进阶方案:使用轻量级迁移(Lightweight Migration),需在初始化时配置
NSPersistentContainer的shouldMigrateAutomatically和shouldInferMappingModelAutomatically为 true。
Q2:保存数据时报错 “A Core Data error occurred.” 怎么办?
排查步骤:
- 检查是否调用了
context.save()(很多人忘了!) - 检查属性是否为 Optional(比如
String?),非 Optional 字段必须赋值 - 在
catch块打印完整错误:print("Error: \(error.localizedDescription)")
Q3:如何查询特定数据?比如“只显示未完成的任务”
修改 @FetchRequest 的 predicate 参数:
@FetchRequest(
entity: Task.entity(),
sortDescriptors: [],
predicate: NSPredicate(format: "isCompleted == false")
) private var incompleteTasks: FetchedResults<Task>
📚 资源推荐:NSPredicate 语法可参考苹果官方文档《Predicate Programming Guide》
Q4:Core Data 和 UserDefaults 有什么区别?
| 特性 | Core Data | UserDefaults |
|---|---|---|
| 适用数据量 | 大量结构化数据(成千上万条) | 小量配置(<1MB) |
| 数据类型 | 自定义对象(Entity) | 基本类型(String, Int, Bool, Array 等) |
| 查询能力 | 支持复杂查询、排序、过滤 | 只能按键取值 |
| 性能 | 高效(懒加载、批量操作) | 小数据快,大数据慢 |
结论:存用户设置用 UserDefaults,存业务数据用 Core Data。
六、学习建议与下一步
你现在已经掌握了 Core Data 的基础用法!接下来可以:
📌 进阶学习路径
- 关系建模:学习 One-to-Many、Many-to-Many 关系(比如“用户”和“订单”)
- 后台线程操作:避免在主线程做大量数据操作(使用
perform或performAndWait) - 数据迁移:当 App 升级需要改模型时,如何平滑迁移用户数据
- 性能优化:使用
fetchBatchSize、setPropertiesToFetch等技巧
🔗 推荐学习资源
- 官方文档:Core Data Programming Guide(必读!)
- 免费教程:Hacking with Swift 的 Core Data 教程
- 视频课程:Stanford CS193p(SwiftUI + Core Data 实战)
💬 最后的话
我当初学 Core Data 时,也被“上下文”、“托管对象”这些术语吓到过。但只要你记住:它只是帮你把对象存到磁盘的工具,一切就简单了。
不要怕犯错——删掉模拟器重装是最有效的调试手段之一。多写几个小 Demo(比如备忘录、联系人列表),很快就能熟练。
希望这篇实践导向的教程能帮你迈出第一步。如果有疑问,欢迎在评论区留言!
🌟 记住:所有复杂的技术,拆解后都不过是“增删改查”。你已经会了!

评论 0