Core Data(Creating and Modifying Custom ManagedObjects)

正如前面所讨论的,托管对象的NSManagedObject实例类,或者NSManagedObject的子类,表示着Entity的实例。NSManagedObject是一个泛型类,这个泛型类实现了所有托管对象(managed object)的基本行为。及可以创建自定义的NSManagedObject 的子类,虽然这不是必要的。如果你不需要对Entity自定义任何逻辑,那么就没有必要为这个Entity创建一个自定义的类。你可以为一下原因自定义类,例如:提供自定义的访问或验证方法,使用非标准的属性,指定相关的密匙,计算得出值,执行其他自定义的逻辑。

创建自定义的托管对象子类(Creating Custom Managed Object Subblasses)

在Objective-C的托管对象子类里,你可以模拟属性(attributes)在接口文件中生命属性(properties),但是你不用声明实例变量。

@interface MyManagedObject : NSManagedObject
 
@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSDate *date;
 
@end

注意,属性(property)必须声明为nonatomic和strong的。处于性能的原因,Core Data通常不会复制(copy)对象的值,即便对象遵循NSCopying协议。

在Objective-C的实现文件中,还必须要指定属性的动态(给property添加一个@dynamic)

@implementation MyManagedObject
@dynamic title;
@dynamic date;
@end

在Swift中,声明属性使用@NSManaged关键词

class MyManagedObject: NSManagedObject {
    @NSManaged var title: String?
    @NSManaged var date: NSDate?
}

Core Data动态生成有效、公共的管理entity的方法,这些方法包括set、get的属性和关系方法。因此,你通常不用编写自定义的建模属性访问器方法。

重写方法指南(Gudelines for Overriding Methods)

NSManagedObject本身就有很多NSObject的特征,这些特征以便于托管对象(managed objects)可以正确的集成到Core Data的基本方法,
Core Data 依赖与NSManagedObject的下列方法实施,你不应该忽略:

  • primitiveValueForKey:
  • setPrimitiveValue:forKey:
  • isEqual:
  • hash
  • superclass
  • class
  • self
  • zone
  • isProxy
  • isKindOfClass:
  • isMemberOfClass:
  • conformsToProtocol:
  • respondsToSelector:
  • managedObjectContext
  • entity
  • objectID
  • isInserted
  • isUpdated
  • isDeleted
  • isFault

在重写(overriding)initWithEntity:insertIntoManagedObjectContext:的方法时遇到阻碍(种类或者类型方面的)。如果在调试(debugging)期间类型缺失或者出错,则结果是不可预知的。通常的可能是没有重写键值编码的方法,例如 valueForKey:、setValue:forKeyPath。

此外,在重写awakeFromInsert,awakeFromFetch,和validateForUpdate:的验证方法前,请求他们父类时(superclass implementaion)要小心,在重写储存器的方法时你可能会对性能产生一些负面影响。

定义属性和数据储存(Defining Properties and Data Storage)

在某些方面,一个托管对象(managed object)就像一个字典一样(dictionary)。它就像一个通用的储存容器一样,有效的提供和储存那些通过NSEntityDescription对象定义的属性。NSManagedObject支持一系列的属性值,常见类型包括:字符串、日期、和数字类型(详情可以参阅NSAttributeDescription)因此,你不必在子类中定义实现变量。但是,如果需要执行非常标准的属性或者保存时区是,你可能要这么做。此外,当你使用了较大的二进制数据时,在你的子类中需要考虑下性能的问题。

使用非标准属性(Using Nonstandard Attributes)

在默认情况下,NSManagedObject储存属性使用的都为内部结构,并且一般情况下Core Data在自己管理的类型(结构)下工作要比自定义的实例类型下工作更为有效。

有时候需要使用不能直接支持的类型,例如,在一个图形应用程序,可能像定义一个具有颜色和范围的实体矩形,也就是NSColor和NSRect的实例。这种情况下就要根据需要创建自己所需的NSManagedObject子类了。

日期,时间和保存时区(Dates, Times, and Preserving Time Zones)

NSManagedObject用NSDate对象来表示日期,储存的时间内部通过基于GMT得到的NSTimeInterval值。因为时区是不确定的--Core Data一般用GMT时间代表日期,这样在数据库中找寻到的时间是标准化的。如果需要保存时区信息,你可以创建一个NSManagedObject的子类来保存。

自定义初始化和释放(Customizing Initialization and Deallocation)

Core Data控制托管对象(managed object)的生命周期。除了断层和撤销,你不能够像处理对待其他标准Objective-C的NSObject类的对象那样进行实例化,破获,和重建。

当托管对象(managed Object)被创键,它将在托管对象的模型(managed object model)中根据它的实体(Entity)得到的默认值进行初始化。在许多的情况下模型中设置的默认值是足够的,有事,可能会使用到模型中不能表示的动态值来执行额外的初始化。

在一个典型的Objective-C的类中,通常重写指定的初始化方法(一般是init方法)。在NSManagedObject的子类中,有三种不同的方法你可以用作重写:initWithEntity:insertIntoManagedObejctContext;, awakeFromInsert, awakeFromFetch。不要重写init方法。建议不要重写initWithEntity:insertIntoManagedObjectContext的方法,重写这个方法造成的状态变化可能会不能正确的结合撤销和重做(undo and redo)。其他 的两种方法,awakeFromInsert和awakeFromFetch用于区分不同的环境。

  • awakeFromInsert在对象(Object)创建时第一个被创建,并且在对象的生命周期中只能调用一次。
    awaakeFromInsert调用之后立即调用initWithEntity:insertIntoManagedObjectContext:或者insertNewObjectForEntityForName:inManagedObjectContext:。可以用awakeFromInsert初始化特殊的属性值,例如对象的时间,如下所示。

Objective-C

- (void)awakeFromInsert
{
    [super awakeFromInsert];
    [self setCreationDate:[NSDate date]];
}

Swift

override func awakeFromInsert() {
    super.awakeFromInsert()
    creationDate = NSDate()
}
  • 当对象从持久化储存中初始化时awakeFromFetch被调用(当获取到值的时候)。
    你可以重写awakeFromFetch,例如创建临时值和其他缓存时。改变处理(change processing)是awakeFormFetch明确禁止的,这样你可以方便使用公共的set访问器而不弄脏(dirtying)对象(Object)或者它的上下文(context)。这中禁止意味着无论如何你都不要对关系进行操作,因为所做的更改将不会正确的传播到目标对象。而更重要的是awakeFromFetch,你可以重写awakeFromFecth或者使用任何运行循环(run loop-related)相关的方法,例如:performSelector:withObject:afterDelay:。

避免重写dealloc时清除临时属性和其他变量,可以重写didTurnIntoFault。当一个对象报错时Core Data会立即自动调用didTurnintoFault的方法变并且立即释放。你可以有效的减少一些托管对象(managed object)错误的内存开支,对于正确的执行清除操作这很重要。

Xcode生成的子类(Xcode Generated Subclasses)

从Xcode8,ios10,macOS10.12开始,Xcode可以自动从Core Data中生成NSManagedObject的子类或者延展(extensions)或者类别(categories)

要在现有的项目中启动此功能,首先要确保数据模型配置正确:
1.选中Core Data的模型文件(Model file),并且打开文件检查程序(open the File inspector)
2.确认工具版本设置Xcode 8或者更高的版本。
3.确认代码生成设置为当前正在使用的语言。

再配置了数据模型之后,可以配置每个实体(Entity):
1.选中要配置的实体(Entity)
2.打开数据模型检查器
3.将代码生成器设置为否(None)、类定义(Class Defintion)或者类别/延展(Category/Extension)


Core data 5.png

在数据模型配置之后,Xcode再生成子类、类别/延展时,相关的实体(Entity)会根据数据模型中的配置生成。

注:
生成的源代码并不包含在项目中(project)中,并打算成为生成过程的一部分。你将无法在项目源列表中查看文件,但是可以在生成目录中查看这些文件。这些文件被经常再生,所以没有手动编辑他们的价值。

如果你希望你的NSManagedObject类添加额外的便利方法或者业务逻辑,你可以创建一个类(Objective-C中)或者延展(swift中),在其中实现方法或者逻辑。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,937评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,503评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,712评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,668评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,677评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,601评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,975评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,637评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,881评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,621评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,710评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,387评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,971评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,947评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,189评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,805评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,449评论 2 342

推荐阅读更多精彩内容

  • 适读对象: 需要入门Core Data的朋友; 像我一样,尚未学过数据库相关课程,不太懂怎么写SQLite语句的朋...
    AntonyWong阅读 5,106评论 8 21
  • 虽然从接触iOS开发开始,做的每一个项目都在用Core Data,但是一些比较底层的东西都是boss写的或者用的是...
    卖萌凉阅读 2,806评论 1 11
  • 引言 在这个教程中,你会看到在Xcode提供的初始化代码模板和数据模型编辑器资源中,用Swift语言写出你的第一个...
    MarkLin阅读 10,138评论 7 32
  • 玲儿静静的看着窗外,她知道,他很快会来,她不知道的只是,他会不会说出她一直在等的那句话。 不一会儿,一个一脸书生气...
    断指鹤阅读 485评论 0 0
  • 有的问题藏在心里就好,强求一个答案到头来受伤的还是自己。
    楚大郎阅读 91评论 0 0