您的位置:首页 > 移动开发 > Swift

iOS Swift教程 Core Data (三)Core Data栈 下

2014-12-31 17:56 453 查看
接下来,我们创建自己的stack object。

创建一个名为CoreDataStack的swift加入到工程中。

转载请注明出处:/article/9358010.html

源代码地址:https://github.com/dnawym/StudySwift/tree/master/CoreData/Dog%20Walk

定义成员变量:

import CoreData

class CoreDataStack {
let context: NSManagedObjectContext
let psc: NSPersistentStoreCoordinator
let model: NSManagedObjectModel
let store: NSPersistentStore?
}


添加辅助函数用于保存数据和获取core data文件所在文件夹路径:

func saveContext() {
var error: NSError? = nil
if context.hasChanges && !context.save(&error) {
println("Could not save: \(error), \(error?.userInfo)")s
}
}

// 获取应用程序documents diretory的url
func applicationDocumentsDirectory() -> NSURL {
let fileManager = NSFileManager.defaultManager()

let urls = fileManager.URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask) as [NSURL]

return urls[0]
}


添加init函数,构造stack

init() {
// 从硬盘加载managed object model,这里通过读取momd目录下的编译后的.xcdatamodeld文件实现
let bundle = NSBundle.mainBundle()
let modelURL = bundle.URLForResource("Dog Walk", withExtension: "momd")
model = NSManagedObjectModel(contentsOfURL: modelURL!)!

// 一旦初始化了NSManagedObjectModel,下一步是创建PSC,PSC用于桥接model和PersistentStore
psc = NSPersistentStoreCoordinator(managedObjectModel: model)

// Context的初始化没有任何参数,我们将psc连接到context上
context = NSManagedObjectContext()
context.persistentStoreCoordinator = psc

// 我们不需要手工创建PS,PSC会帮我们创建它。我们只需要为PSC提供所需的PS类型,一些配置,存放路径即可
let documentsURL = applicationDocumentsDirectory()
let storeURL = documentsURL.URLByAppendingPathComponent("Dog Walk")

let options = [NSMigratePersistentStoresAutomaticallyOption: true]

var error: NSError? = nil
store = psc.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: storeURL, options: options, error: &error)

if store == nil {
println("Error adding persistent store: \(error)")
abort()
}
}


修改AppDelegate文件,构造CoreData'Stack并传递给ViewController,同时添加2个函数在应用程序进入后台和即将结束时,保存数据到文件系统中

import UIKit
import CoreData

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

var window: UIWindow?

lazy var coreDataStack = CoreDataStack()

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

let navigationController = self.window!.rootViewController as UINavigationController
let viewController = navigationController.topViewController as ViewController

viewController.managedContext = coreDataStack.context

return true
}

func applicationDidEnterBackground(application: UIApplication) {
coreDataStack.saveContext()
}

func applicationWillTerminate(application: UIApplication) {
coreDataStack.saveContext()
}

}


在ViewController中添加ManagedObjectContext成员变量

var managedContext: NSManagedObjectContext!


数据建模:

创建名为Dog Walk的CoreData model文件,在其中添加2个entity





这里,回到Dog Entity界面,创建一个指向walk的relationship



默认情况下,这种关系都是一对一的,这里需要修改为一对多,并且勾选Ordered,这样,数据自动按日期进行排序。



接下来,选择walk entity,创建一个inverse relationship指回dog,这里不用修改成to many,因为一次walk只会关联到一条狗



inverse的作用是让model知道如何找到反向路径。比如,对于一个walk记录,通过relationship可以找到对应的dog,通过inverse,model知道通过walks关系可以回到walk记录。通过选择右下角的按钮来切换视图模式到图像编辑模式。to-one是单箭头,to-many是双箭头。



创建ManagedObjectModel的子类,选择Dog Walk model并选择Dog和Walk这两个entity,最后记得选择swift编程语言,这样会生成Dog.swift和Walk.swift


然后,修改Dog和Walk数据模型的属性,将Dog改为Dog_Walk.Dog,将Walk改为Dog_Walk.Walk。这一步的目的是连接managed object子类的全名到data model中的entity。



实现对数据的持久存储:

前面我们已经完成了Core Data栈的创建,data model子类的创建,接下来我们修改ViewController来使用Core Data。

var currentDog: Dog!


override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "Cell")

let dogEntity = NSEntityDescription.entityForName("Dog", inManagedObjectContext: managedContext)

let dog = Dog(entity: dogEntity!, insertIntoManagedObjectContext: managedContext)

let dogName = "Fido"
let dogFetch = NSFetchRequest(entityName: "Dog")
dogFetch.predicate = NSPredicate(format: "name == %@", dogName)

var error: NSError? = nil
let result = managedContext.executeFetchRequest(dogFetch, error: &error) as [Dog]?

if let dogs = result {
if dogs.count == 0 {
currentDog = Dog(entity: dogEntity!, insertIntoManagedObjectContext: managedContext)
currentDog.name = dogName

if !managedContext.save(&error) {
println("Could not save: \(error)")
}
} else {
currentDog = dogs[0]
}
} else {
println("Could not fetch: \(error)")
}
}
接下来,修改add函数,首先创建一个walk entity并设置它的date属性,然后将这个walk实例加入到dog的walks集合中。因为dog的walks集合是immutable的,我们需要先创建一个mutable的拷贝,再将walk插入到copy中,最后将拷贝赋值回dog覆盖以前的set。

@IBAction func add(sender: AnyObject) {

// 插入新的Walk entity到Core Data中
let walkEntity = NSEntityDescription.entityForName("Walk", inManagedObjectContext: managedContext)
let walk = Walk(entity: walkEntity!, insertIntoManagedObjectContext: managedContext)

walk.date = NSDate()

// 插入新的walk到dog的walks集合中
var walks = currentDog.walks.mutableCopy() as NSMutableOrderedSet
walks.addObject(walk)
currentDog.walks = walks.copy() as NSOrderedSet

// 保存managed object context
var error: NSError?
if !managedContext.save(&error) {
println("Could not save: \(error)")
}

tableView.reloadData()
}
从Core Data中删除数据:

添加下述函数到ViewController:

func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete {
// 获取要删除的walk对象
let walkToRemove = currentDog.walks[indexPath.row] as Walk

// 类似于添加walk到walks,现获取一个mutable拷贝,然后在拷贝中移除对应的walk,最后将拷贝赋值回dog
let walks = currentDog.walks.mutableCopy() as NSMutableOrderedSet
walks.removeObjectAtIndex(indexPath.row)
currentDog.walks = walks.copy() as NSOrderedSet

// 删除walk对象
managedContext.deleteObject(walkToRemove)

// 保存
var error: NSError?
if !managedContext.save(&error) {
println("Could not save: \(error)")
}

// 从table view中删除当前行
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: UITableViewRowAnimation.Automatic)
}
}
程序执行效果:



至此,我们就完成了3个实例,遛狗程序。这一节中,我们学习了如何构建自己的Core Data栈,数据模型和managed object子类,以及如何建立实例之间的关系,如何操作关系以及如何从Core Data中删除数据。

接下来,我们会更深入的学习fetch和其它更高级的iOS8 topics,这一节我们学习了基本的操作,但是还有更多需要学习的地方,are you ready?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: