初探 iOS Core Data

前言

Core Data 是 Apple 官方推出的数据持久化框架。如果我们的应用程序需要缓存数据以便在我们的程序没有网络的时候也可以使用,我们就可以采用 Core Data 来存储我们需要的数据。

并且它可以通过 CloudKit,在单个 iCloud 账户中的多个设备自动同步缓存的数据。

通过 XCode 中的 Data Model 编辑器,我们可以自定义数据的类型和关系,并生成相应的类文件。Core Data 提供以下几项特性:

  • 数据持久化:Core Data抽象了将对象映射到磁盘的细节,使得保存数据变得容易,开发者无需直接管理数据库。
  • 支持单个或批量的撤销、重做操作:Core Data的撤销管理器可以跟踪更改,并可以单独回滚,分组回滚,或者一次全部回滚,这使得在应用程序中添加撤销和重做支持变得很容易。
  • 保持数据与视图同步:Core Data还通过为表和集合视图提供数据源来帮助保持视图和数据同步。
  • 支持版本控制和迁移。

创建 Core Data 的数据模型

我们可以在创建项目的时候,在 Storage 这一项勾选 Core Data。这样,XCode 会自动帮我们创建好一个以项目名命名的 Core Data 文件:

  • 勾选位置:
  • 以项目名命名的 Core Data 文件:

如果想在已存在的项目中添加 Core Data ,可以 command + N 新建文件,选择 iOS 平台,然后搜索框输入 data model 检索:

创建好 Core Data 文件,我们就可以使用 XCode 添加 Entity 了。选中创建的文件进入编辑界面,点击左下角的 Add Entity

双击创建好的 Entity 可以重命名,点击右侧的 Attributes 下面的➕添加字段:

准备工作完成,下面介绍一下它的基本使用。

基本使用

如果要使用 Core Data,我们需要以下几个类的协同合作来完成:

  • NSManagedObjectModel 的实例代表了你的应用的模型文件,它描述了你的应用的类型、属性和关系。
  • NSManagedObjectContext 的实例跟踪应用程序类型实例的变化。
  • NSPersistentStoreCoordinator 的实例保存并从 store 中获取应用类型的实例。
  • NSPersistentContainer 的实例一次设置了模型、上下文和存储协调器。

初始化 Core Data 示例代码如下:

swift 复制代码
lazy var persistentContainer: NSPersistentCloudKitContainer = {
        let container = NSPersistentCloudKitContainer(name: "FamilyMedicalRecords")
        // Load any persistent stores, which creates a store if none exists.
        container.loadPersistentStores { _, error in
            if let error {
                // Handle the error appropriately. However, it's useful to use
                // `fatalError(_:file:line:)` during development.
                fatalError("Failed to load persistent stores: \(error.localizedDescription)")
            }
        }
        return container
}()

func save() {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        do {
            try context.save()
        } catch {
            // Replace this implementation with code to handle the error appropriately.
            // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            let nserror = error as NSError
            fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
        }
    }
}

下面就以 User(只包含一个 String 类型的 name 属性) 举例来看一下 Core Data 的增删改查操作。首先,我们先生成一下 NSManagedObject Subclass,选中 Core Data 文件 -> 选中 Entity ---> 选择 Editor -> 选择 Create NSManagedObject Subclass 即可 :

然后将 Entity 的 Codegen 改为 Manual/None

Insert 操作

添加数据的示例代码:

swift 复制代码
func insertUser(name: String) {
    do {
        let context = persistentContainer.viewContext
        let entity = NSEntityDescription.entity(forEntityName: userEntityName, in: context)
        
        let user = User(entity: entity!, insertInto: context)
        user.name = name
        save()
    } catch {
        fatalError("Failed to fetch Users: \(error)")
    }
}

首先我们需要获取当前 Core Data 的上下文:context。然后使用 NSEntityDescription 初始化 entity。接着创建 user,最后调用 save() 保存即可。

Delete 操作

删除操作的示例代码:

scss 复制代码
func deleteUsers(user: User) {
    let context = persistentContainer.viewContext
    context.delete(user)
    save()
}

直接调用 context 的 delete() 函数,然后调用 save() 函数即可。

Select 操作

获取全部用户的示例代码:

swift 复制代码
func fetchUsers() -> [User] {
    let context = persistentContainer.viewContext
    var users = [User]()
    do {
        users = try context.fetch(User.fetchRequest())
    } catch {
        fatalError("Failed to fetch users: \(error)")
    }
    return users
}

获取上下文,context 调用 fetch 函数即可。

Tips:fetchRequest() 是在进行 NSManagedObject Subclass 时系统自动生成的代码。

Update 操作

修改示例代码:

scss 复制代码
func updateUsers(user: User) {
    user.name = "hello, world"
    save()
}

修改 name 的值,然后调用 save() 函数即可。

相关推荐
HarderCoder1 天前
Swift 6 并发时代,如何优雅地“抢救”你的单例?
swift
zhangmeng1 天前
FlutterBoost在iOS26真机运行崩溃问题
flutter·app·swift
HarderCoder1 天前
SwiftUI 踩坑记:onAppear / task 不回调?90% 撞上了“空壳视图”!
swift
HarderCoder1 天前
@isolated(any) 深度解析:Swift 并发中的“隔离追踪器”
swift
大熊猫侯佩2 天前
桃花岛 Xcode 构建秘籍:Swift 中的 “Feature Flags” 心法
app·xcode·swift
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
光影少年2 天前
webpack打包优化
webpack·掘金·金石计划·前端工程化
HarderCoder2 天前
Swift 6.2 新特性 `@concurrent` 完全导读
swift
HarderCoder2 天前
Swift 里的“橡皮擦”与“标签”——搞懂 existentials 与 primary associated type
swift