前面讲解了 Core Data 的框架,并完全手动编写代码演示了 Core Data 的运作过程。下面我们来演示如何结合 XCode 强大的可视化编辑以及 Cocoa 键值编码,绑定机制来使用 Core Data。有了上面提到的哪些利器,在这个示例中,我们无需编写 NSManagedObjectModel 代码,也无需编写 NSManagedObjectContext,工程模版在背后为我们做了这些事情。
今天要完成的这个示例,有两个 Entity:StudentEntity 与 ClassEntity,各自有一个名为 name 的 Attribute。其中 StudentEntity 通过一个名为 inClass 的 relationship 与 ClassEntity关联,而 ClassEntity 也有一个名为 students 的 relationship 与 StudentEntity 关联,这是一个一对多的关系。此外 ClassEntity 还有一个名为 monitor 的 relationship 关联到 StudentEntity,表示该班的班长。代码下载:
最终的效果图如下:下面我们一步一步来完成这个示例:
1,创建工程:创建一个 Cocoa Application,工程名为:MacCoreData,并勾选 Create Document-Based Application 和 Use Core Data,在这里要用到 Core Data 和 Document 工程模版,以简化代码的编写。2,分类文件:
在 MacCoreData 下新建 Src 和 Res 两个 Group,并将 MyDocument.h 和 MyDocument 拖到 Src 下,将其他 xib 和 xcdatamodeld 拖到 Res 中。将文件分类是个好习惯,尤其是对大项目来说。后面请自觉将文件分类~~3,创建 Entity:
在工程中,我们可以看到名为 MyDocument.xcdatamodeld 的文件,其后缀表明这是一个 core data model文件,框架就是读取该模型文件生成模型的。下面我们选中这个文件,向其中添加两个实体。点击下方的 Add Entity 增加两个新 Entity: ClassEntity 和 StudentEntity。向 StudentEntity 中添加名为 name 的 string 类型的 Attribute,并设置其 Default Value 为学生甲,去除 Optional 前勾选状态;
向 ClassEntity 中添加名为 name 的 string 类型的 Attribute,并设置其 Default Value 为XX班,去除 Optional 前勾选状态;选项 Optional 是表示该 Attribute 可选与否的,在这里 name 都是必须的。向 StudentEntity 中添加名为 inClass 指向 ClassEntity 的 Relationship,其 Inverse 栏要等 ClassEntity 添加了反向关系才能选择,后面回提到;
向 ClassEntity 中添加名为 students 指向 StudentEntity 的 Relationship,其 Inverse 栏选择 inClass,表明这是一个双向关系,勾选 To-Many Relationship,因为一个班级可以有多名学生,这是一对多关系。设定之后,我们可以可以将 StudentEntity 的 inClass 关系的 Inverse 设置为 students了。再向 ClassEntity 中添加名为 monitor 指向 StudentEntity 的 Relationship,表示该班的班长。4,生成 NSManagedObject 类:
选中 StudentEntity,然后点击菜单 File-> New -> New file…,添加 Core Data -> NSManagerObject subclass, XCode 就会自动为我们生成 StudentEntity.h 和 StudentEntity.m 文件,记得将这两个文件拖放到 Src Group 下。下面我们来看看这两个文件中有什么内容:StudentEntity.h[cpp]
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class ClassEntity;
@interface StudentEntity : NSManagedObject {
@private
}
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) ClassEntity * inClass;
@end
StudentEntity.m
[cpp]
#import "StudentEntity.h"
#import "ClassEntity.h"
@implementation StudentEntity
@dynamic name;
@dynamic inClass;
@end
[cpp]
if (value == [self monitor])
[self setMonitor:nil];
[cpp]
if ([value containsObject:[self monitor]])
[self setMonitor:nil];
5,下面来生成 UI 界面:
在这里,我们是通过切换 view 的方法来显现学生与班级两个界面,因此我们需要主界面,班级以及学生共三个界面。向 MyDocument.xib 中添加如下一个 popup button 和一个 NSBox。并删除 popup 控件中的 menu item,因为我们要通过代码来添加班级,学生项的。![](http://static.oschina.net/uploads/img/201312/19211423_Rp0k.png)
![](http://static.oschina.net/uploads/img/201312/19211423_iD9e.png)
6,添加 ViewController:
下面我们创建 ViewController 来在程序中转载 xib 文件,显示和切换 view。为了便于切换 view,我们创建一个继承自 NSViewController 的名为:ManagedViewController的类(记得不要创建该类对应的 xib 文件!创建一个 NSObject子类,然后修改其父类为 NSViewController),然后让 StudentViewController 和 ClassViewController 从它继承。ManagedViewController 类的代码如下:ManagedViewController.h[cpp]
#import <Cocoa/Cocoa.h>
@interface ManagedViewController : NSViewController {
@private
NSManagedObjectContext * managedObjectContext;
NSArrayController * contentArrayController;
}
@property (nonatomic, retain) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, retain) IBOutlet NSArrayController *contentArrayController;
@end
[cpp]
#import "ManagedViewController.h"
@implementation ManagedViewController
@synthesize managedObjectContext;
@synthesize contentArrayController;
- (void)dealloc
{
self.contentArrayController = nil;
self.managedObjectContext = nil;
[super dealloc];
}
// deal with "Delete" key event.
//
- (void) keyDown:(NSEvent *)theEvent
{
if (contentArrayController) {
if ([theEvent keyCode] == 51) {
[contentArrayController remove:nil];
}
else {
[super keyDown:theEvent];
}
}
else {
[super keyDown:theEvent];
}
}
@end
ClassViewController 类的代码如下:
[cpp]
#import "ManagedViewController.h"
@interface ClassViewController : ManagedViewController {
@private
}
@end
#import "ClassViewController.h"
@implementation ClassViewController
- (id)init
{
self = [super initWithNibName:@"ClassView" bundle:nil];
if (self) {
[self setTitle:@"班级"];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end
[cpp]
#import "ManagedViewController.h"
@interface StudentViewController : ManagedViewController {
@private
}
@end
#import "StudentViewController.h"
@implementation StudentViewController
- (id)init
{
self = [super initWithNibName:@"StudentView" bundle:nil];
if (self) {
[self setTitle:@"学生"];
}
return self;
}
- (void)dealloc
{
[super dealloc];
}
@end