Core Data by tutorials 笔记(一)

最近花了半个月读完了Raywenderlich家的《Core Data by Tutorials》,接下来几天就做个回顾,笔记并不是对原书的简单翻译,算是对整个知识脉络的一个整理的过程吧:)

Update: 上周去搞Sketch了,工具算是基本入门了,抄了几个图标,画了几个图,以后会再聊聊。好了,进入正题吧,今天打算介绍前三章,也是CoreData的最基础的部分。*

Chapter 1:Your First Core Data App

第一章比较简单,主要是带你熟悉CoreData的用法,并用CoreData创建了一个简单的List APP,学完这章你能加满如下技能点:

  • model data you want to store in Core Data using Xcode’s model editor;
  • add new records to Core Data;
  • fetch a set of records from Core Data;
  • display the fetched results to the user in a table view.

第一章按顺序大致如下:

一、Getting started

作者提供了一个Start Project,打开其实就是一个UITableViewController,你需要做的就是增加一个addName方法,这里使用了UIAlertController这个iOS 8新添加的方法来做数据的添加逻辑,使用起来也很优雅。

二、Modeling your data

这个主要是根据你的数据模型创建对应的managed object model,主要操作也在.xcdatamodeld中进行,全GUI操作,没什么难度。

You can think of a Core Data entity as a class “definition” and the managed object as an instance of that class. 这里作者用了面向对象的思想做了类比,虽然不是很准确,但也方便初学者理解。

三、Saving to Core Data

这里要注意到NSManagedObject的“对象”其实是遵循“KVC”的,NSManagedObject对象的值改变后,在ManagedContext中进行save操作。

四、Fetching from Core Data

创建一个NSFetchRequest对象,设置好各种条件,依旧是交给ManagedContext对象去执行。下面是作者描述了两种fetch失败的情况

If there are no objects that match the fetch request’s criteria, the method returns an optional value containing an empty array. If an error occurred during the fetch, the method returns an optional value that contains nil. If this happens, you can inspect the NSError and respond appropriately.

第一章到此结束:)


Chapter 2:NSManagedObject Subclasses

NSManagedObject上一章我们提到过,要存取属性,只能用KVC,使用起来既不安全也不符合面向对象的原则,所以我们这章要生成他的子类,来创建我们自己的属性,这样就又能愉快地使用"."语法啦。

第二章的大致顺序如下:

一、Getting started

作者提供了一个“挑选领结”的Start Project,领结数据存放在plist文件中,同样是一个很简单的App。

二、Modeling your data

打开xcdatamodeld文件进行编辑,添加属性。这里主要看一下Binary DataTransformable两种类型:

  • Binary Data这里将image对象保存成了二进制文件,当然任何可以序列化的对象其实都可以保存成二进制。这里作者强调了性能问题,如果将一个很大的二进制保存到SQLite数据库中很可能会产生卡顿等问题。当然,幸运的是Core Data提供了一种叫Allows External Storage的解决方式,他只对binary data的属性类型有效,你只需要简单的开启他就好了。

    When you enable Allows External Storage, Core Data heuristically decides on a per-value basis if it should save the data directly in the database or store a URI that points to a separate file.

  • Transformable除了一些基本属性,如果一个对象遵循NSCoding Protocol,那么这个对象是可以选择使用transformable类型的,作者这里使用的是UIColor类型,遵循NSSecureCoding协议,而该协议又继承自NSCoding,所以设为Transformable是OK的。自定义的类想要设置为Transformable,那么你首先要实现NSCoding protocol

三、Managed object subclasses

在Xcode中选择Editor\Create NSManagedObject Subclass创建managedObject对象的子类,这里注意下Map Model中的attribute type与实际子类对象中的属性的对应关系就好了

  • 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

当然如果你想保留Map Model中的原始基本类型,那么在创建NSManagedObject Subclass时要勾选Use scalar properties for primitive data types

Similar to @dynamic in Objective-C, the @NSManaged attribute informs the Swift compiler that the backing store and implementation of a property will be provided at runtime instead of at compile time. 这里注意下两种语言的一点区别

创建完子类还要记得一点就是在Model中的Attributes inspectorclass name设为你新生成的子类路径,完成这一步主要是为了在runtime时将managed object subclass与Model中的entity链接起来。(有点类似与在SB中创建一个VC,并设置他的custom class)。

四、Propagating a managed context

因为Xcode默认的CoreData模板会将context在AppDelegate中创建,所以,就会有这种获取context的做法:

let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate  

但这种做法还是不推荐使用,较好的方法是能够在对象的的初始化中将context作为参数进行传递。 接下来,作者从plist中将数据通过子类对象导入到core data中,再对界面做了些操作,这都比较简单。

五、Data validation in Core Data

数据校验这里可以在data model inspector 中设置最大最小值,如果出错会在context save的时候将错误信息传给error参数

第二章到此结束:)


Chapter 3:The Core Data Stack

Core Data要正常运行,需要几个组件共同协作来完成,这些组件包括:

  • NSManagedObjectModel
  • NSPersistentStore
  • NSPersistentStoreCoordinator
  • NSManagedObjectContext

这些组件共同构成了Core Data Stack,组件间的关系我觉得用苹果官方提供的一张图来展示最好不过了

  • An external persistent store that contains saved records.
  • A persistent object store that maps between records in the store and objects in your application.
  • A persistent store coordinator that aggregates all the stores.
  • A managed object model that describes the entities in the stores.
  • A managed object context that provides a scratch pad for managed objects.

基本Core Data整个操作都是围绕这张图来做的,本章作者给出的例子是一个记录狗狗🐶散步的APP,按照时间顺序添加散步记录。

第三章的大致顺序如下:

一、The managed object model

The NSManagedObjectModel 反映了APP中所有的对象类型在data model中所拥有的属性,以及对象之间的关系。作者还提到了我们用Xcode提供的visual editor创建/编辑了一个xcdatamodel file,然而真正在幕后的是一个叫momc的编译器(compiler),把model file编译后的结果放到momd文件夹下。Core Data可以很高效地在运行时使用momd文件夹里编译过的内容,来初始化一个NSManagedObjectModel实例。

二、The persistent store

Core Data提供了四种开箱即用的NSPersistentStore存储类型,三种原子型atomic的,一种非原子型non-atomic

An atomic persistent store needs to be completely deserialized and loaded into memory before you can make any read or write operations. In contrast, a non- atomic persistent store can load chunks of itself onto memory as needed.

  • NSQLiteStoreType 依托SQLite数据库,也是唯一的非原子型的non-atomic
  • NSXMLStoreType 依托于XML文件,是原子型的atomic
  • NSBinaryStoreType 依托于二进制文件,是原子型的atomic
  • NSInMemoryStoreType 其实是存在于内存中persistent store type,不算严格意义上的持久化存储,通常用来做单元测试和缓存。

除了上述介绍过的存储类型,作者说了,只要你的数据类型是基于JSON和CSV的格式,你还可以通过创建NSIncrementalStore的子类来创建自己的persistent store类型。

Incremental Store Programming Guide

三、The persistent store coordinator

NSPersistentStoreCoordinator可以看成是一座连接managed object model与persistent store的桥梁,他负责理解model,更好地来处理信息的存取。特别是有多个persistent stores时,persistent store coordinator相对managed context提供唯一的接口,保证了context与特定的persistent store交互。

四、The managed object context

之前的章节提到过context可以看做是内存中的scratchpad,来记录所有的managed object的行为,当然managed object所做的任何改变,在context没有save()之前,都是不会在数据库中生效的。

作者又提到了关于context的五个比较重要的特性:

  1. The context 管理着对象们的生命周期,不管这些对象是create还是fetch到的,这种对生命周期的管理在faulting、inverse、relationship handling 和 validation时很有用。
  2. A managed object不能脱离context而存在,他们是紧紧地绑在一起的。
  3. contexts都很有领土意识👏,一旦一个managed object被归到某个context中去了,那么这个managed object在他整个生命周期内属于这个context了。
  4. 一个应用可以使用多个context,大多非凡的Core Data应用都这么搞。
  5. A context是非线程安全的,你最好不要跨线程去使用context,Apple提供了多种方式来在多线程中使用context,后面会讲到。

五、Creating your stack object

创建自己的core data stack,其实只要记住本章开始那张图,记住要创建四个对象以及他们之间的关系,创建起来还是比较简单的。

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

你要做到工作就是创建这些对象以及他们之间的关系,具体代码见苹果官方提供的Snippet

创建完毕,使用起来也相当简单,这里注意使用Lazy来懒加载

lazy var coreDataStack = CoreDataStack()  

六、Modeling your data

接下来就是在Xcode里创建model,这里也没什么难度。增加两个Entity,设置他们的关系为一对多,并在一对多的关系下面的Arrangement那里勾选Ordered

七、Adding managed object subclasses

这里通过Xcode生成的子类要注意一下,刚才一对多的关系因为上图勾选了Ordered,所以这里生成了一个NSOrderedSet类型的对象。一开始我“以为这个真是一个有序集合,CoreData会为这个集合里的子对象们排序”,但经过和@Kyrrr同学讨论试验,发现并不是这么一回事。真正的原因是集合里的子对象们都是无序的,本来应该用数组。但数组保证不了子对象的唯一性,所以才用了集合。而使用有序集合只是为了将来使用起来索引方便,而并不是排序。作者下面也有提到:

NSSet seems like an odd choice, doesn’t it? Unlike arrays, sets don’t allow accessing their members by index. In fact, there’s no ordering at all! Core Data uses NSSet because a set forces uniqueness in its members. The same object can’t feature more than once in a to-many relationship.

这里同样要注意的一点,还是创建完子类记得去model对应的Entity那里,Data Model inspector下填写相应的Class路径。

八、A walk down persistence lane

接着就去ViewController做一些工作来使用CoreData,完成狗狗散步的App,这一步也比较简单。

九、Deleting objects from Core Data

删除一条记录,先删除context中的相应object,保存后,从UI中删去相关条目。


-EOF-

如果感觉此文对你有帮助,请随意打赏支持作者 😘

chengway

认清生活真相之后依然热爱它!

Subscribe to Talk is cheap, Show me the world!

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!