SwiftUI存储之CoreData初始化Stack

设置Core Data Stack

如果我们在项目设置期间选中了“Use Core Data”复选框,则Xcode会将“CoreData”堆栈的代码放入应用程序委托中。这是我不喜欢的事情,我们不会因Core Data堆栈的设置而使应用程序代表混乱。

文章推荐

推荐代码

相反,我们将创建一个单独的类,负责设置和管理核心数据堆栈。创建一个新组并将其命名为“Managers”。在“Managers”组中创建一个新的Swift文件,并将其命名为CoreDataManager.swift。 CoreDataManager类负责应用程序的Core Data堆栈。

将Foundation框架的导入语句替换为Core Data框架的导入语句。

import CoreData

接下来,我们定义类本身。请注意,我们将CoreDataManager类标记为final。它不打算被子类化。

import CoreData

final class CoreDataManager {

}

我们要提供给Core Data Manager的唯一信息是数据模型的名称。我们首先为数据模型的名称创建一个属性。该属性的类型为String。

import CoreData
 
 final class CoreDataManager {
 
     // MARK: - Properties
 
     private let modelName: String
 
}

类的指定初始值设定项接受数据模型的名称作为参数。

 import CoreData
  
  final class CoreDataManager {
  
      // MARK: - Properties
  
      private let modelName: String
 
    // MARK: - Initialization

     init(modelName: String) {
        self.modelName = modelName
     }
 
 }

请注意我们需要实现Core Data Stack的三个对象:

  • a managed object model
  • a managed object context
  • a persistent store coordinator

首先,为每个对象创建一个lazy属性。这些属性被标记为私有。但是请注意,我们仅将managedObjectContext属性的设置器标记为私有。需要访问核心数据堆栈的其他对象应该可以访问核心数据管理器的托管对象上下文。请记住,托管对象上下文是我们最常使用的对象。这是核

private(set) lazy var managedObjectContext: NSManagedObjectContext ={}()
private lazy var managedObjectModel: NSManagedObjectModel = {}()
private lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {}()

Managed Object Context

让我们从实现ManagedObjectContext属性开始。我们通过调用其指定的初始化程序init(concurrencyType :)来初始化NSManagedObjectContext类的实例。此初始化程序接受类型为NSManagedObjectContextConcurrencyType的参数。我们传入mainQueueConcurrencyType,这意味着托管对象上下文与应用程序的主队列或主线程关联。我们将在本书后面的内容中详细了解线程。现在不用担心。

// Initialize Managed Object Context
let managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

请记住,每个父级受管对象上下文都引用了核心数据堆栈的持久性存储协调器。这意味着我们需要设置托管对象上下文的persistentStoreCoordinator属性。

// Configure Managed Object Context
managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator

并且我们从闭包中返回托管对象上下文。

private(set) lazy var managedObjectContext: NSManagedObjectContext ={
// Initialize Managed Object Context
let managedObjectContext =NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

// Configure Managed Object Context
 managedObjectContext.persistentStoreCoordinator = self.persistentStoreCoordinator
 return managedObjectContext
}()

Managed Object Model

初始化管理对象模型很容易。我们向应用程序bundle索要数据模型的URL,然后使用该URL实例化NSManagedObjectModel类的实例。

// Fetch Model URL
guard let modelURL = Bundle.main.url(forResource: self.modelName, withExtension: "momd") else {
    fatalError("Unable to Find Data Model")
}

// Initialize Managed Object Model
guard let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) else {
10     fatalError("Unable to Load Data Model")
}

我们从闭包中返回managed object model 。

private lazy var managedObjectModel: NSManagedObjectModel = {
 // Fetch Model URL
guard let modelURL = Bundle.main.url(forResource: self.modelName , withExtension: "momd") else {
      fatalError("Unable to Find Data Model")
   }

// Initialize Managed Object Model
guard let managedObjectModel = NSManagedObjectModel(contentsOf: modelURL) else {
        fatalError("Unable to Load Data Model")
    }

return managedObjectModel
}()

Persistent Store Coordinator

难题的最后一部分是持久存储协调员。这有点复杂。我们首先使用托管对象模型实例化NSPersistentStoreCoordinator类的实例。但这只是第一步。

// Initialize Persistent Store Coordinator
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

只有将持久性存储添加到持久性存储协调器后,Core Data堆栈才起作用。我们首先为持久性存储创建URL。有几个存储永久存储的位置。在此示例中,我们将持久性存储存储在应用程序沙箱的“文档”目录中。但是您也可以将其存储在Library目录中。

我们将sqlite附加到数据模型的名称上,因为我们将使用SQLite数据库作为持久性存储。请记住,Core Data开箱即用地支持SQLite数据库。

// Helpers
let fileManager = FileManager.default
let storeName = "\(self.modelName).sqlite"

// URL Documents Directory
let documentsDirectoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

// URL Persistent Store
let persistentStoreURL = documentsDirectoryURL.appendingPathComponent(storeName)

由于添加持久性存储可能会失败,因此我们需要在do-catch语句中执行它。要添加持久性存储,我们在持久性存储协调器上调用addPersistentStore(ofType:configurationName:at:options :)。
此方法接受四个参数:

  • 持久存储的类型,在此示例中为SQLite
  • 可选配置
  • 持久性存储的位置
  • 选项的可选词典
do {
// Add Persistent Store
let options = [ NSMigratePersistentStoresAutomaticallyOption : true, NSInferMappingModelAutomaticallyOption : true ]
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: persistentStoreURL, options : options)
 } catch {}

如果持久性存储协调器在我们指定的位置找不到持久性存储,它将为我们创建一个持久性存储。如果在指定位置已经存在一个持久性存储,则将其添加到持久性存储协调器。这意味着永久存储是在用户第一次启动您的应用程序时自动创建的。第二次,Core Data查找持久性存储,在指定位置找到它,然后“将其添加到持久性存储协调器中。该框架为您处理。

在catch子句中,如果操作失败,则将错误输出到控制台。我们从闭包中返回持久性存储协调器。

private lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
// Initialize Persistent Store Coordinator
let persistentStoreCoordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

// Helpers
let fileManager = FileManager.default
let storeName = "\(self.modelName).sqlite"

// URL Documents Directory
let documentsDirectoryURL = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]

// URL Persistent Store
let persistentStoreURL = documentsDirectoryURL.appendingPathComponent(storeName)

do {
// Add Persistent Store
try persistentStoreCoordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: persistentStoreURL, options: nil)

   } catch {
        fatalError("Unable to Add Persistent Store")
    }

return persistentStoreCoordinator
}()

技术交流

QQ:3365059189
SwiftUI技术交流QQ群:518696470

请关注我的专栏icloudend,

https://www.jianshu.com/c/7b3e3b671970

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容