第3章Core Data数据持久化技术
Core Data是苹果为OS X和iOS系统应用开发提供的数据持久化技术。它基于高级数据持久化API,它的底层最终是SQLite数据库、二进制文件和内存数据保存,这样开发人员不用再关心数据的存储细节问题,不用再使用SQL语句,不用面对SQLite的C语言函数。
3.1对象关系映射
Core Data是一种对象关系映射(Object Relational Mapping,ORM)技术。听说过HibernateHibernate是一个开放源代码的对象关系映射Java EE框架。的人对对象关系映射不会感到陌生,对象关系映射是关系数据模型和对象模型类之间的一个纽带。
图31对象关系映射
无论哪一种模型,都是为了描述和构建应用系统。在应用系统中,一个基本的概念是“实体”。“实体”是应用系统中的“人”、“事”和“物”,它们能够在构造关系模型和对象模型中以不同的形态存在。如图31所示,实体在关系模型中代表表的一条数据,该表描述了实体的结构有哪些属性和关系。实体在对象模型中代表类的一个对象,类描述了实体的结构,实体是类的对象。因此,表是与类对应的概念,记录是与对象对应的概念。
关系模型和对象模型是有区别的,对象模型更加先进,能够描述继承、实现、关联、聚合和组成等复杂的关系,而关系模型只能描述一对一、一对多和多对多的关系。这两种模型之间的不和谐称为“阻抗不匹配”问题,而对象关系映射可以解决“阻抗不匹配”问题。
3.2Core Data堆栈
使用Xcode工具,可以很方便地为工程添加Core Data支持。在Xcode的工程模板中,有两个模板(MasterDetail Application和Single View Application模板)可以直接为工程添加Core Data支持,具体方法是创建工程时,选中Use Core Data复选框,如图32所示。
图32添加Core Data支持
其他的模板需要自己添加Core Data支持。下面看看通过模板生成的代码,这些代码主要生成在AppDelegate中。AppDelegate.swift中的主要代码如下:
import UIKit
import CoreData
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
…
// MARK: - Core Data 堆栈
lazy var managedObjectModel: NSManagedObjectModel = {①
…
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {②
…
}()
lazy var managedObjectContext: NSManagedObjectContext? = { ③
…
}()
…
}
在AppDelegate.swift中,代码第①行定义了NSManagedObjectModel类型的属性,代码第②行定义了NSPersistentStoreCoordinator类型的属性,代码第③行定义了NSManagedObjectContext类型的属性。
上述属性的类型含义如下所示:
□NSManagedObjectContext。它是被管理对象上下文(Managed Object Context,MOC)类,在上下文中可以查找、删除和插入对象,然后通过Core Data堆栈同步到持久化对象存储。
□NSManagedObjectModel。它是被管理对象模型(Managed Object Model,MOM)类,是系统中的“实体”,与数据库中的表等对象对应。
□NSPersistentStoreCoordinator。它是持久化存储协调器(Persistent Store Coordinator, PSC)类,在持久化对象存储之上提供了一个接口,可以把它考虑成为数据库的连接。
除了上述3个概念外,还有“持久化对象存储”,它们一起构成了Core Data堆栈。持久化对象存储(Persistent Object Store,POS)执行所有底层的从对象到数据的转换,并负责打开和关闭数据文件。它有3种持久化实现方式: SQLite、二进制文件和内存形式。
Core Data堆栈如图33所示,有一个或多个被管理对象上下文,它连接到一个持久化存储协调器。一个持久化存储协调器连接到一个或多个持久化对象存储。持久化对象存储与底层存储文件关联。一个持久化存储协调器也可以管理多个被管理对象模型。一个持久化存储协调器就意味着一个Core Data堆栈。通过Core Data堆栈,可以实现数据查询、插入、删除和修改等操作。
下面看看AppDelegate.swift中的saveContext方法,其代码如下所示:
func saveContext () {
if let moc = self.managedObjectContext {
var error: NSError? = nil
if moc.hasChanges && !moc.save(&error) {
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()
}
}
}
图33Core Data堆栈
当插入、删除和修改数据之后,需要通过该方法保存被管理对象上下文,其中self.managedObjectContext{}语句是保存上下文的核心语句。
在AppDelegate.swift中,applicationDocumentsDirectory方法的代码如下:
lazy var applicationDocumentsDirectory: NSURL = {
let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory,
inDomains: .UserDomainMask)
return urls[urls.count-1] as NSURL
}()
该方法返回应用程序沙箱Documents目录,它的返回类型是NSURL。
在AppDelegate.swift中,Core Data堆栈的方法如下:
//返回被管理对象上下文
lazy var managedObjectContext: NSManagedObjectContext? = {①
let coordinator = self.persistentStoreCoordinator②
if coordinator == nil {
return nil
}
var managedObjectContext = NSManagedObjectContext()③
managedObjectContext.persistentStoreCoordinator = coordinator④
return managedObjectContext
}()
//返回持久化存储协调器
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {⑤
var coordinator: NSPersistentStoreCoordinator?
= NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)⑥
let url = self.applicationDocumentsDirectory
.URLByAppendingPathComponent("xcdatamodeld文件.sqlite")
var error: NSError? = nil
var failureReason = "There was an error creating or loading the application's saved data."
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType,
configuration: nil, URL: url, options: nil, error: &error) == nil {⑦
coordinator = nil
// 发生错误情况下处理
let dict = NSMutableDictionary()⑧
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved
data"
dict[NSLocalizedFailureReasonErrorKey] = failureReason
dict[NSUnderlyingErrorKey] = error
error = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)⑨
NSLog("Unresolved error \(error), \(error!.userInfo)")
abort()⑩
}
return coordinator
}()
//返回被管理对象模型
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle()
.URLForResource("HelloWorld", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
上面的3个属性是计算属性,它们的调用顺序如图34所示。
图34Core Data堆栈的调用顺序
第①行代码managedObjectContext属性返回MOC对象。第②行代码是调用persistentStoreCoordinator属性获得PSC对象,第③行代码用于实例化MOC对象,第④行代码通过managedObjectContext.persistentStoreCoordinator = coordinator语句设置PSC数据持久化类型。
第⑤行代码中的persistentStoreCoordinator属性返回PSC对象。第⑥行代码用于实例化PSC对象,第⑦行代码使用addPersistentStoreWithType:configuration:URL:options:error:方法为PSC对象添加新的持久化数据存储。addPersistentStoreWithType参数用于指定存储类型,它的取值可以是下面的3个常量。
□NSSQLiteStoreType。指数据持久化类型是SQLite数据。
□NSBinaryStoreType。指数据持久化类型是二进制文件。
□NSInMemoryStoreType。指数据持久化类型是内存形式。
如果在代码第⑦行添加新的持久化数据存储失败,则通过代码⑧~⑩行输出错误日志,并终止任务,其中代码第⑧~⑨行是准备NSError对象,代码第⑩行abort()函数是终止任务。
……
展开