1 import UIKit
2 import CoreData
3
4 // coredata管理器
5 class CoreDataManager: NSObject {
6
7 // 单例
8 static let sharedManager:CoreDataManager = CoreDataManager()
9
10 // 私有化构造函数
11 override private init(){
12 super.init()
13 }
14
15 // 持久化容器,可以提供管理上下文
16 // iOS10推出,为了兼容低版本,我们这里设置private,不再使用,手动方式实现管理对象上下文,见下一个属性
17 // 包含了CoreDataStack中的所有核心对象,下面是很重要的三个对象
18 // viewContext: NSManagedObjectContext - 管理上下文,主要负责数据操作
19 // managedObjectModel: NSManagedObjectModel - 管理对象模型
20 // persistentStoreCoordinator: NSPersistentStoreCoordinator
21 private lazy var persistentContainer: NSPersistentContainer? = {
22
23 // CoreData的核心对象都不是线程安全的
24 // 使用同步锁/互斥锁,保证线程安全
25 objc_sync_enter(self)
26 // 实例化对象,需要指定数据模型
27 // 指定的名称 == 数据模型的名称 == 沙盒中数据库的名称
28 // let container = NSPersistentContainer(name: "demo_db")
29
30 // 管理对象模型,参数传入nil,自动将mainBundle中所有的数据模型合并
31 let model = NSManagedObjectModel.mergedModel(from: nil)!
32
33 // 实例化持久化容器
34 // 参数一:数据库名字
35 // 参数二:合并后的模型
36 var container:NSPersistentContainer? = NSPersistentContainer(name: "ys.db", managedObjectModel: model)
37
38
39 // “同步方式” 加载 “持久化存储” -> 本质是 打开/新建/修改数据库(同步方式,保证线程安全)
40 container?.loadPersistentStores(completionHandler: { (storeDescription, error) in
41 // 判断创建数据库是否出现错误
42 if let error = error as NSError? {
43 /*
44 常见错误:
45 1、目录不存在,或者禁止写入,无法创建数据库文件
46 2、设备存储空间不足
47 3、由于权限或设备锁定时的数据保护,不能访问持久化存储
48 4、数据库不能被迁移到当前模型版本
49 */
50 print("打开/新建/修改数据库出现错误:\(error)")
51 container = nil
52 }
53 })
54
55 objc_sync_exit(self)
56
57 return container
58 }()
59
60 // 管理对象上下文
61 lazy var moc:NSManagedObjectContext? = {
62 // 同步锁/互斥锁保护
63 objc_sync_exit(self)
64
65 // 实例化管理上下文
66 var mocObj:NSManagedObjectContext? = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)
67
68 // 实例化对象模型
69 let momObj = NSManagedObjectModel.mergedModel(from: nil)!
70
71 // 持久化存储调度器
72 let psc = NSPersistentStoreCoordinator(managedObjectModel: momObj)
73
74 // 添加数据库
75 // 参数1:数据存储类型
76 // 参数3:保存SqLite数据库文件的URL
77 // 参数4:设置数据库选项
78 let cacheDir = NSSearchPathForDirectoriesInDomains(.cachesDirectory, .userDomainMask, true).last!
79 let path = (cacheDir as NSString).appendingPathComponent("ys.db")
80 let dict = [NSMigratePersistentStoresAutomaticallyOption:true,
81 NSInferMappingModelAutomaticallyOption:true]
82
83 let persistentStore = try? psc.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: URL(fileURLWithPath: path), options: dict)
84
85 if persistentStore != nil{
86 // 给管理上下文指定存储调度器
87 mocObj?.persistentStoreCoordinator = psc
88 }
89 else{
90 print("打开/新建/修改数据库出错")
91 mocObj = nil
92 }
93
94 objc_sync_exit(self)
95
96 return mocObj
97 }()
98
99 // 保存上下文
100 func saveContext () {
101 if let context = moc{
102 // 事务:可以保存多个数据,不一定每次数据发生变化都需要保存,可以一次性保存
103 if context.hasChanges {
104 do {
105 try context.save()
106 } catch {
107 let nserror = error as NSError
108 print("保存数据出错:\(nserror)")
109 }
110 }
111 }
112 }
113 }