1 概念介绍
什么是coreData?
coreData
是一个对象图管理器(object graph management)以及一个 ios与osx的sdk的数据持久化框架(persistence framework)
意思是coreData可以 存储
且 取回数据
但是
他并不是类似Mysql以及 SQLite 一样的关系型数据库
尽管 他可以背后可以使用 sqlite作为数据存储的工具
2 coreData的 Data Model 的配置页面
2.1 entity
core Data中是一个类的定义, 在关系数据库中,对应的就是 table
2.2 attribute
attribute 指的是一个类的属性
2.3 relationship
指的是多个实体间的link。
一对一的link 称为: to-one relationship
一对多的link 称为: to-many relationship
3 kvc key- value coding or KVC.
3.1 如何使用KVC
kvc 是Cocoa和 Cocoa Touch中的一种利用 字符串string来 标示 属性的机制, 从这个角度来说,kvc有些像一个字典dict
所有继承自 NSObject
的类,包括NSManageObject
, kvc
都是适用的
对于非继承自
NSObject
的类,是不能使用kvc的。
见如下示例
// 从NSManageObject 中取出属性
cell.textLabel.text = person.valueForKey("name") as String
// 往NSObject 中添加元素
person.setValue(name, forKey: "name")
3.2 不使用kvc的理由
虽然我们可以使用kvc对NSManagedObject 直接的做一系列操作,但是 最大
的问题是,我们是通过字符串在访问对象,而不是 强类型的类 ,各种各样的拼写错误,可能导致很多错误。没有充分的利用xcode的类型检查以及 自动补全 功能
The biggest problem with key-value coding is the fact that you’re accessing of data using strings instead of strongly-typed classes.
3.3 替换kvc,自动生成NSManagedObject Subclass 的方法
最好的更换kvc的方法,就是为data model中出现的每一个entity 编写 NSManagedObject subclass
The best alternative to key-value coding is to create NSManagedObject subclasses for each entity in your data model
编写好的dataModel ,可以直接使用
xcode的editor-> Create NSManagedObject Subclass
来自动生成
类型的定义如下
• String maps to String
• Integer 16/32/64, Float, Double and Boolean map to NSNumber
• Decimal maps to NSDecimalNumber
• Date maps to NSDate
• Binary data maps to NSData
• Transformable maps to AnyObject
If you want to work directly with primitive data types such as Double and Int32, you could have checked the box next to
Use scalar properties for primitive data types
in the last dialog when you were generating the managed object subclass
4 coreData的简单使用示例
4.1 save代码 保存 示例代码与解释
func saveName(name: String) {
//1
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
//2
let entity = NSEntityDescription.entityForName("Person", inManagedObjectContext:
managedContext)
let person = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
//3
person.setValue(name, forKey: "name")
//4
var error: NSError?
if !managedContext.save(&error) {
println("Could not save \(error), \(error?.userInfo)") }
//5
people.append(person)
}
代码解释如下
- 在save与retrieve数据之前,你首先需要控制一个
NSManageObjectContext
的对象, 可以将一个managed object context
对象看做一个再系统内存中的 managed object的中间结果暂存器。
把一个managed Object存到 CoreData分为两个步骤
一. 将一个 managed Object 对象存入 一个managed Object context中
二. 将你的managed Object context中的改变提交,并存到磁盘中
xcode中已经在你点击 use coreData的checkbox 的时候,就已经创建了一个 managed Object context作为项目模板的一部分。 这个默认的 moc,是作为app delegate
的属性 存在的,为了获取moc
, 我们首先需要获取app delegate
的一个引用 便有了// 1
的代码
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
二. 你创建了一个新的 managed object,并且将其 insert进入了 moc
通过使用 NSManagedObjectContext
的构造器。
// 创建一个新的对象
// NSManagedObject 是一个 “shape-shifter” 他可以表示任何的entity,而NSEntityDescription 则是在运行时用于连接 一个 NSManagedObject的实例 与 entity 的 数据模型
let entity = NSEntityDescription.entityForName("Person", inManagedObjectContext:
managedContext)
// 将对象插入 moc中,使用NSManagedObject的构造器
let person = NSManagedObject(entity: entity!, insertIntoManagedObjectContext:managedContext)
三. 当拥有了一个 NSManagedObject 之后,使用 kvc , 将属性添加到 NSManagedObject中,这里的属性 名称必须和你再datamodel中建立的entity的attribute name要保持一致
person.setValue(name, forKey: "name")
四.
// 4
中的代码表示的就是将你的改变提交给 person,并且将它save到disk中。通过调用save的方法。
if there is ever an error with the save operation, you can inspect the error and alert the user if necessary.
4.2 fetch data的代码示例以及解释
if let managedContext = (UIApplication.sharedApplication().delegate as! AppDelegate).managedObjectContext {
let fetchRequest = NSFetchRequest(entityName: "Person")
var error: NSError?
let fetchedResults = managedContext.executeFetchRequest(fetchRequest, error: &error) as! [NSManagedObject]?
if let results = fetchedResults {
people = results
}else {
println("Can't fetch data \(error), \(error!.userInfo)")
}
}
其中 fetchrequest 有很多 qualifiers 用于 改进 结果的返回,NSEntityDescription 是其中必备的之一。
代码中 用构造器的方式,获取了特定entity的所有对象
5 entity的类型
大部分的类型都是显而易见的。这里主要介绍两个
- transformable
利用 transformable 类型,我们可以存储任何类型的数据,甚至是我们自己定义的类型,
只要你的类型实现了NSCoding protocol
例如
UIColor conforms to NSSecureCoding, which inherits from NSCoding, so it can use the transformable type out of the box.
- binary data
可以存储一些二进制数据,比如图片,或者文档。
6 传播context
再4中我们说到,每次首先都要取得 managed object context 这个一个对象,那就要写如下的代码
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let managedContext = appDelegate.managedObjectContext!
一次还好,如果每个 controller中都需要有许多个删除以及添加的地方,就会很麻烦。
解决办法还是有的,我们知道,context再程序创建的时候就已经有了。在appdelegate 中。我们需要做的就是将appdelegate中的context传递给相应controller的局部变量。
- 首先,再viewController中创建一个MOC的变量。
import CoreData
var managedContext: NSManagedObjectContext!
- 然后,再AppDelegate 中的didfinish方法中添加
let viewController = self.window?.rootViewController as! ViewController
viewController.managedObjectContext = self.managedObjectContext
这样,日后转场的时候,就可以将这个MOC 的prepareForSegue方法中继续传递下去。