来聊下Core Data

来聊下Core Data

IOS小彩虹2021-07-19 6:05:27180A+A-

在单个设备上持久化(persist)缓存(cache)数据,并且支持撤销(undo)

使用Core Data来保存你的应用程序的**永久性(permanent)数据供离线使用,缓存临时(temporary)**数据,并在单个设备上为应用程序添加撤销功能。

通过Core Data数据模型编辑器,你可以定义数据类型和关系,并生成(generate)相应的类定义。Core Data可以在运行时管理对象实例(instances),并提供以下特性(features)

持久化(Persistence)

Core Data将对象**映射到(mapping ... to)存储的细节抽象(abstracts)出来,使得在不直接管理(administering)**数据库的情况下从Swift和OC中保存数据变得很容易。

撤回和重做

Core Data 的撤回管理器会跟踪变化,并且可以单个(individually)、**整组(groups)或者一次性地(all at once)回滚(roll ... back)**数据,可以方便地使你的程序支持撤回和重做。

img

后台数据任务

尽可能地(potentially)将可能阻塞UI(UI-blocking)的数据任务(例如解析(parsing)JSON到对象)放在后台(in the background),然后可以缓存或者存储(store)结果以减少(reduce)服务器往返(roundtrips)

与视图同步(synchronization)

Core Data还通过为表和集合(collection)视图提供(providing)数据源,帮助保存视图和数据同步(synchronized)

版本控制(Versioning)与迁移(Migration)

Core Data 包含随着应用程序的发展(evolves)而对数据模型进行版本控制(versioning)迁移(migrating)用户数据的机制(mechanisms)

创建数据模型

想要使用 Core Data 功能的第一步就是创建一个数据模型文件,然后在该文件中定义应用程序对象的结构,包括它们的对象类型、属性和关系。

你可以在创建Xcode项目时选择添加Core Data模型文件到你的项目中,你也可以将模型文件添加到一个已有的项目中。

创建项目时添加Core Data

在创建项目的弹窗中,选择使用Core Data选项。

之后你就可以在你的项目中看到后缀名为 .xcdatamodeld 的文件

添加Core Data模型文件到一个已有项目中

选择 File -> New -> File 在打开的弹窗中选择 iOS 分组中的Data Model选项。

点击下一步(Next),设置模型文件的名字,并选择导入到本项目中。

之后你就会发现一个后缀为 .xcdatamodeld 的文件已经添加到你的项目中了。

创建Core Data数据栈

当你创建了数据模型文件后,接下来就是设置模型层类以辅助(collaboratively)支持(support)你的应用。这些类统称为Core Data Stack(核心数据栈)

  • NSManagedObjectModel 的**实例(instance)表示应用程序的模型文件,该文件描述(describing)**了程序的类型(types),属性(properties)以及关系(relationships)

  • NSMangedObjectContext 实例(instance)可以跟踪(tracks)程序类型实例(instance of your app's types)变化(changes)

  • NSPersistentStoreCoordinator 实例(instance)保存(saves)并从存储(store)获取(fetches)程序类型的实例(instances of your app's types)

  • NSPersistentContainer 实例一次性设置模型(model)上下文(context)以及存储(store)协管器(coordinator)

初始化Persistent Container

通常来说,Core Data的初始化(initialize)是在应用创建(startup)时候(during)。使用**懒加载(lazy)变量(variable)延迟(defer)创建持久化容器(persistent container)实例,直到程序代理(delegate)**第一次使用 Core Data。

如果你在创建Xcode项目是选择了Core Data选项,则**模版(template)自动(automaticallye)**包含这些设置代码。

class AppDelegate: UIResponder, UIApplicationDelegate {

    ...

    lazy var persistentContainer: NSPersistentContainer = {        
        let container = NSPersistentContainer(name: "DataModel")
        container.loadPersistentStores { description, error in
            if let error = error {
                fatalError("Unable to load persistent stores: \(error)")
            }
        }
        return container
    }()

    ...
}
  1. 声明(declare)一个 NSPersistentContainer 类型的懒加载(lazy)变量(variable)
  2. 创建一个持久化容器(persistent container)实例(instance),将数据模型文件名传递(passing)给它的初始化器(initializer)
  3. 加载(load)持久化存储(persistence stores),如果不存在持久化存储的实例,则会创建一个。

一次创建之后,持久化容器将分别(respectively)在其managedObjectModel、viewContext以及persistentStoreCoordinator属性中保存对模型、上下文和存储协调器实例的引用(references)

之后可以将容器的引用传递到用户界面中。

将持久化容器引用传递给视图控制器

在程序的根视图,import CoreData 并且创建一个变量来存放持久化容器的引用。

import UIKit
import CoreData

class ViewController: UIViewController {

    var container: NSPersistentContainer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        guard container != nil else {
            fatalError("This view needs a persistent container.")
        }
        // The persistent container is available.
    }
}

回到程序代理。在 application(_:didFinishLaunchingWithOptions:)中,设置根组件控制器,并设置持久化容器。

class AppDelegate: UIResponder, UIApplicationDelegate {

    ...

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {        
        if let rootVC = window?.rootViewController as? ViewController {
            rootVC.container = persistentContainer
        }        
        return true
    }

    ...
}

为了将持久化容器**传递(pass)其他(additional)视图控制器中,在每个视图控制器中重复(repeat)创建(creation)一个容器变量,并在视图的上层(previous)**视图使用prepare(for:sender:)设置它们的值。

class ViewController: UIViewController {

    ...
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if let nextVC = segue.destination as? NextViewController {
            nextVC.container = container
        }
    }
}

子类化(subclass)持久化容器

NSPersistentContainer可以(intended)被子类化(to be subclassed)。子类是存放 Core Data 相关代码的区域(place),可以**方便(convenient)我们进行数据的管理,例如设置一个返回数据子集(subsets of data)**或者将数据持久化到磁盘的函数。

import CoreData

class PersistentContainer: NSPersistentContainer {    

    func saveContext(backgroundContext: NSManagedObjectContext? = nil) {
        let context = backgroundContext ?? viewContext
        guard context.hasChanges else { return }
        do {
            try context.save()
        } catch let error as NSError {
            print("Error: \(error), \(error.userInfo)")
        }
    }    
}

上面(above)示例(example)向容器中添加了一个saveContext函数,以便在发生更改时保存上下文,从而提高(imporve)性能(performance)

注意:当将模型层分解(factoring)为自己的框架时,NSPersistentContainer子类(subclass)在自己的包(bundle)中定位(locates)模型文件。

手动(manually)设置Core Data栈

NSPersistentContainer 支持iOS 10.0+ 以及 macOS 10.12+,如果需要**部署(deploying)较早(earlier)版本的系统,你需要手动(manually)实例化(instantiate)**一个NSManagedObjectModel、一个NSPersistentStoreCoordinator以及至少一个NSManagedObjectContext

创建一个托管对象模型

实例化(instantiate)NSManagedObjectModel时,你需要传入(pass in)一个指向(points to) .xcdatamodeld 文件的编译版本(compiled version)URL,这个 .momd 文件通常(typically)是应用程序包(app bundle)一部分(part of)

guard let modelURL = Bundle.main.url(forResource: "DataModel",
                                     withExtension: "momd") else {
    fatalError("Failed to find data model")
}
guard let mom = NSManagedObjectModel(contentsOf: modelURL) else {
    fatalError("Failed to create model from file: \(modelURL)")
}

创建持久化(persistent)存储(store)协调器(coordinator)

接着,向NSPersistentStoreCoordinator初始化器传入(pass)已载入的(loaded)模型,用于创建一个关联的(associated)存储(store)协调器(coordinator)

let psc = NSPersistentStoreCoordinator(managedObjectModel: mom)

添加一个持久化存储

如果你希望Core Data持久化你的数据模型到硬盘,只需要告诉存储协调器什么时候写入(reside)文件以及怎么格式化(format)

let dirURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).last
let fileURL = URL(string: "DataModel.sql", relativeTo: dirURL)
do {
    try psc.addPersistentStore(ofType: NSSQLiteStoreType,
                               configurationName: nil,
                               at: fileURL, options: nil)
} catch {
    fatalError("Error configuring persistent store: \(error)")
}

每种可用的(available)存储类型都有其优点(advantages)缺点(disadvantages),详情请参考NSPersistentStoreCoordinator的相关文档说明。

创建一个托管对象上下文

创建一个NSManagedObjectContext对象,并设置存储协调器属性(property)。

let moc = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
moc.persistentStoreCoordinator = psc

应用程序与Core Data的**大部分(bulk of)交互(interaction)都是在这个上下文中进行的。通过引用(reference)将此上下文传递(pass)**给用户界面,详情请查看将持久化容器引用传递给视图控制器

点击这里复制本文地址 以上内容由权冠洲的博客整理呈现,请务必在转载分享时注明本文地址!如对内容有疑问,请联系我们,谢谢!

支持Ctrl+Enter提交

联系我们| 本站介绍| 留言建议 | 交换友链 | 域名展示
本站资源来自互联网收集,仅供用于学习和交流,请遵循相关法律法规,本站一切资源不代表本站立场,如有侵权、后门、不妥请联系本站删除

权冠洲的博客 © All Rights Reserved.  Copyright quanguanzhou.top All Rights Reserved
苏公网安备 32030302000848号   苏ICP备20033101号-1

联系我们