初探 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 中的不透明类型与装箱协议类型:概念、区别与实践
swift
HarderCoder1 小时前
Swift 泛型深度指南 ——从“交换两个值”到“通用容器”的代码复用之路
swift
东坡肘子2 小时前
惊险但幸运,两次!| 肘子的 Swift 周报 #0109
人工智能·swiftui·swift
胖虎12 小时前
Swift项目生成Framework流程以及与OC的区别
framework·swift·1024程序员节·swift framework
songgeb18 小时前
What Auto Layout Doesn’t Allow
swift
YGGP1 天前
【Swift】LeetCode 240.搜索二维矩阵 II
swift
YGGP2 天前
【Swift】LeetCode 73. 矩阵置零
swift
非专业程序员Ping3 天前
HarfBuzz 实战:五大核心API 实例详解【附iOS/Swift实战示例】
android·ios·swift
Swift社区4 天前
LeetCode 409 - 最长回文串 | Swift 实战题解
算法·leetcode·swift
YGGP6 天前
【Swift】LeetCode 54. 螺旋矩阵
swift