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

接下来,我们创建自己的stack object。

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

转载请注明出处:http://blog.csdn.net/yamingwu/article/details/42297675

源代码地址: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?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值