CoreData学习:Core Data Stack(Swift)

Posted Longshihua

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CoreData学习:Core Data Stack(Swift)相关的知识,希望对你有一定的参考价值。

   Core Data是苹果官方提供的一套框架,用来解决对象生命周期管理、对象关系图管理和持久化等方面相关的问题。Core Data是模型层的技术,Core Data帮助你构建代表程序状态的模型层。Core Data也是一种持久化技术,它可以将模型的状态持久化到磁盘。但它更重要的特点是:Core Data不只是一个加载和保存数据的框架,它也能处理内存中的数据。

什么是Core Data

     对于Core Data框架将经常困惑,以为是数据库。其实Core Data并不是数据库。如果它不是数据库,那么Core Data是什么?Core Data是应用中的模型层,也就是我们ios常用Model-View-Controller模式中的ModelCoreDataOS XiOS SDK中的对象图形管理和持久化存储框架。这意味着CoreData能够存储和获取数据,但是CoreData并不是关系型数据库。

Core Data
堆栈(Core Data Stack)

   Core Data Stack
Core Data的核心部分。拥有一系列关键的对象,堆栈中关键的对象是管理对象模型(managed object model), 持久化存储协调器(persistent store coordinator),一个或者多个管理对象上下文(managed object contexts).

下面一起看一下各个组成部分:

NSManagedObjectModel

   管理对象模型(managed object model)代表着应用中的数据模型(data model)。虽然Core Data不是数据库,但是能够把管理对象模型(managed object model)比喻为数据库的模式,它包含了对象图形中的实体(entities),实体的属性,实体之间的关系。
   NSManagedObjectModel对象能够知道在它进行初始化的时候,数据模型(data model)会加载一个或者多个数据模型文件。

NSPersistentStoreCoordinator

   正如名字所表达的意思一样,NSPersistentStoreCoordinator对象持久化保存数据到磁盘并且确保持久存储(persistent store(s))和数据模型(data model)的兼容性。它是持久存储和管理对象上下文之间的协调者,同时也负责加载和缓存数据。可以说,NSPersistentStoreCoordinatorCore Data的指挥核心,虽然在Core Data stack堆栈中地位非常重要,但是我们很少直接与它进行交互,上下文已经封装了对它的调用。

NSManagedObjectContext

     管理对象上下文(NSManagedObjectContext)对象管理者一系列的模型对象,也就是NSManagedObject类的实例,即我们通常所了解的实体(Entities).应用中很有可能存在多个NSManagedObjectContext,每一个管理对象上下文背后都将有一个持久化存储协调者作为支撑。
   我们可以了解NSManagedObjectContext为一个工作台,我们使用其中的模型对象进行工作,我们加载模型对象,改变模型对象,以及保存模型对象等一系列操作都是在工作台中进行的。当从数据持久层获取数据时,相当于把这些临时的数据拷贝写在上下文,上下文充当一个临时缓冲层,然后就可以随心所欲的修改这些值。通过上下文,可以对数据记录NSManagedObject进行添加删除更改,记录更改后支持撤销和重做,除非你保存这些数据变化,否则持久层的东西是不会变化。

理解几点:

1
:上下文主要是管理管理者对象
2
:在Core Data中所做的所有的操作都是在上下文中进行的。
3
:我们所做的任何改变将不能够影响存储在磁盘中的数据,一直到我们调用上下文的save方法进行保存。
4
:上下文管理着管理者对象的生命周期。生命周期的管理有着强大的特征,比如反转关系,处理验证。
5
:管理者对象如果不与上下文联系将不会存在,事实上,管理者对象和它的上下文是非常紧密的联系在一起,每一个管理者对象都有引用一个上下文,比如:let managedContext = employee.managedObjectContext
6
:上下文拥有着自己的区域,一旦管理对象已经跟特定的上下文相关联,在对象的整个生命周期都将和相同的上下文想关联在一起!
7
:一个应用可以使用多个上下文,这是Core Data强大的一方面.
8
:上下文对象不是线程安全的,只能够在相同的线程让管理者对象和上下文进行交互。Apple也提出了许多的方式使上下文能够在多线程应用中进行工作。

接下来探索一下Core Data Stack

1
:创建工程

选中Xcode在菜单栏选择File>New > Project,我们选择iOS > Application模块下的Single View Application,如下图:

技术分享


工程命名和相关设置如下图,要记得选中Use Core Data,这里使用Swift语言。

技术分享


2:了解工程代码

     默认情况下,在应用的AppDelegate.swift文件中,将为我们提供一些与Core Data相关的代码。在文件的顶部我们将看到导入了Core Data 框架。那是因为在创建工程的时候,选中Use Core Dataxcode将在AppDelegate.Swift自动为我们生成相关Core Data stack 代码.


import UIKit

import CoreData


AppDelegate类中还包含了四个懒加载的存储属性:

applicationDocumentsDirectory 类型为NSURL

managedObjectModel类型为  NSManagedObjectModel

managedObjectContext类型为 NSManagedObjectContext

persistentStoreCoordinator类型为  NSPersistentStoreCoordinator


下面一起了解一下各个属性:


applicationDocumentsDirectory属性

       以如下简单的代码方式创建文件存储目录,NSFileManager用于获取文件的目录。
    lazy var applicationDocumentsDirectory: NSURL = {
        // The directory the application uses to store the Core Data store file. This code uses a directory named "hua.Core_Data_Stack" in the application's documents Application Support directory.
        let urls = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
        return urls[urls.count-1]
    }()

managedObjectContext

   managedObjectContext:我们经常使用它与Core Data进行交互。managedObjectContext的初始化操作在闭包中进行。

     在闭包中,我们首先引用持久化存储协调者,然后在初始化managedObjectContext的时候配置.MainQueueConcurrencyType为参数,我们将在后续的文章中了解更多有关于并发类型。使用.MainQueueConcurrencyType表示managedObjectContext默认在主线程列队中进行工作。

     在我们返回managedObjectContext对象之前,我们需要设置persistentStoreCoordinator属性,没有persistentStoreCoordinator对象,managedObjectContext将毫无用处。

    lazy var managedObjectContext: NSManagedObjectContext = {
        // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) This property is optional since there are legitimate error conditions that could cause the creation of the context to fail.
        let coordinator = self.persistentStoreCoordinator
        var managedObjectContext = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
        managedObjectContext.persistentStoreCoordinator = coordinator
        return managedObjectContext
    }()


persistentStoreCoordinator

     正如我们前面所看到的,在配置managedObjectContext的时候有访问persistentStoreCoordinator属性,下面我们看一下实现,代码看起来有点多,但是不要担心,我们一点一点分析。

 lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator = {
        // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it. This property is optional since there are legitimate error conditions that could cause the creation of the store to fail.
        // Create the coordinator and store
        let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
        let url = self.applicationDocumentsDirectory.URLByAppendingPathComponent("SingleViewCoreData.sqlite")
        var failureReason = "There was an error creating or loading the application's saved data."
        do {
            try coordinator.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: nil)
        } catch {
            // Report any error we got.
            var dict = [String: AnyObject]()
            dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
            dict[NSLocalizedFailureReasonErrorKey] = failureReason

            dict[NSUnderlyingErrorKey] = error as NSError
            let wrappedError = NSError(domain: "YOUR_ERROR_DOMAIN", code: 9999, userInfo: dict)
            // Replace this with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
            NSLog("Unresolved error \(wrappedError), \(wrappedError.userInfo)")
            abort()
        }
       
        return coordinator
    }()

      在闭包中,首先我们初始化NSPersistentStoreCoordinator类的实例,传入管理对象模型(managedObjectModel)作为参数,后面我们将学习managedObjectModel属性。正如我们所看到的,创建NSPersistentStoreCoordinator对象是非常容易的,但是NSPersistentStoreCoordinator并没有使用任何的持久化管理,所以在闭包中,我们将加载持久化存储(persistent store)并添加到persistentStoreCoordinator

     同时我们也指定了具体的存储路径,使用applicationDocumentsDirectory属性。

     最后使用NSPersistentStoreCoordinator类的实例方法,addPersistentStoreWithType(_:configuration:URL:options:)进行添加持久化存储,该方法接收4个参数,第一个类型存储类型,我们指定了存储类型为NSSQLiteStoreType,第二个参数用于配置persistent store,传入nil,将使用默认配置。第三个参数是数据存储的位置,即我们事先创建的url路径。第四个参数是一个字典,用于对persistent store进行配置,暂时传入nil

     因为addPersistentStoreWithType是可出错的,所以我们使用do-catch进行捕获异常,如果没有错误将添加persistent storepersistentStoreCoordinator上。如果添加persistent store错误,那么意味着persistent store有问题,我们需要采取相应的步骤解决,在catch闭包中我们打印了错误的原因并且调用了abort方法。注意:我们不能够在生产环境调用该方法,它会让应用奔溃。


补充一点:


Core Data提供了4NSPersistentStore方式:3个原子性的一个非原子性的:在我们进行任何的读数据或者写数据操作之前需要对原子性持久化存储进行完全的反序列化并加载到内存。相反,非原子性存储能够加载自己的块到存储,如果需要。

简单的预览一下Core Data内嵌的持久化存储类型:

1NSQLiteStoreType是由SQLite database支持。这是Core Data唯一种非原子的存储类型,有着轻量和高效的存储使用,在大多数iOS工程中,这是最好的选择,Xcode中的Core Data 模板,默认就是使用NSQLiteStoreType类型进行存储。

2NSXMLStoreType支持xml文件,是所有类型中最可读性最好的,这种存储类型为原子存储,所以它需要大量的存储使用,NSXMLStoreType类型只适用于OS X

3NSBinaryStoreType支持二进制数据文件存储,跟NSXMLStoreType一样,也是原子性存储方式。所以在我们做任何操作之前,整个的二进制文件必须已经加载到内容。在真实的APP中,很少使用该类型进行存储。

4NSInMemoryStoreType是一种内存持久化存储类型。在某种程度上,这种存储类型并不是真正的持久化。当APP终止或者在iPhone中退出,那么存储在内存中的数据将消失,所以基本上适用于进行单元测试和一些类型的缓存。


managedObjectModel


闭包中的实现非常简单,应用模型的存储位置是modelURL,并且使用modelURL初始化NSManagedObjectModel类,因为初始化返回额可选值,所以在返回之前我们要进行解包。

lazy var managedObjectModel: NSManagedObjectModel = {
    // The managed object model for the application. This property is not optional. It is a fatal error for the application not to be able to find and load its model.
    let modelURL = NSBundle.mainBundle().URLForResource("Core_Data_Stack", withExtension: "momd")!
    return NSManagedObjectModel(contentsOfURL: modelURL)!
}()


在工程导航的左边,我们可以看到Core_Data_Stack.xcdatamodeld文件,该应用数据模型会被编译为.momd文件,该.momd文件管理对象模型。如下图:


技术分享

工程中很有可能会有一些数据模型文件,NSManagedObjectModel类能够合并多个数据模型(data model)到一个,这是Core Data一个强大和高级的特性。 Core Data framework也支持数据模型版本控制和版本迁移,这能够确保存储在持久化存储中的数据不会被损坏。数据模型文件为空意味着数据模型中并没有包含实体。


最后我们通过一张图来理解Core Data stack中的各个部分:


    
技术分享

1:正如上图所示,NSPersistentStoreCoordinatorCore Data的大脑,它能够有一个或者多个persistent stores并且确保数据的保存,加载和缓存等操作。

2NSPersistentStoreCoordinator通过NSManagedObjectModel知道数据模型。管理对象模型将通过一个或者多个.momd文件创建应用的数据模型

3:应用将通过一个或者多个NSManagedObjectContext类获取对象图形,一个管理对象上下文将通过持久化存储协调器(persistent store coordinator)知道数据模型,管理对象上下文并不知道或者保持引用管理对象模型(managed object model),事实上并不需要这样的引用。当有必要的时候,managed object context 将要求persistent coordinator保存数据。Core Data是模型层的技术。Core Data帮助你构建代表程序状态的模型层。Core Data也是一种持久化技术,它可以将模型的状态持久化到磁盘。但它更重要的特点是:Core Data不只是一个加载和保存数据的框架,它也能处理内存中的数据。



























































以上是关于CoreData学习:Core Data Stack(Swift)的主要内容,如果未能解决你的问题,请参考以下文章

带有 Core Data 陡峭学习曲线的 RestKit 0.10.1

NSFetchedResultsController 是不是应该始终与 Core Data 一起使用?

深入理解Core Data

RestKit / Core Data:远程删除的实体不会从 Core Data 中删除

ios/xcode/core data:更新屏幕的最佳方式

使用 Core Data 时是不是需要本地数组?