当工程很大,涉及多个功能模块时。往往需要使用到多个数据库。当CoreData框架开发具有多个模块的工程时,也需要建立多个数据库,具体方法如下:
第一步:新建实体模板,一般一个功能模块对应一个数据库,一个实体模板对应一个上下文对象。即需要将一个功能模块所涉及的所有实体都新建在一个对应的实体模板。对应关系:一个功能模块——>一个实体模板——>上下文对象——>一个数据库,然后由新建好的实体模板生成对应的实体类。
此步骤需要注意的问题:
问题一:当在一个完成好的工程内增添功能模块,这时需要新建与功能模块对应的实体模板。新建好实体模板之后必须将此软件卸载再重新安装,主要是为了完全清除沙盒内旧的数据库文件。
问题二:当在完整的工程内修改模板结构后,一定要将此模板对应的实体类重新删除再重新生成(因为模板结构已经改变也就意味着模板内与修改后实体对应的实体类也需要修改),然后再卸载程序重新安装。
问题三:在生成模板内对应的实体类时一定要注意实体类的生成顺序,必须先生成只具有基本属性的非嵌套类然后再生成具有relationship的嵌套类(因为嵌套类是基于非嵌套类的)。
第二步:新建与每一个模板所对应的上下文全局属性变量(因为只有上下文对象处理数据的全部操作)。
第三步:新建NSManagedObjectModel类的对象,用于读取实体模板的内容。并如果只有一个模块可以使用NSManagedObjectModel类的类方法mergedModelFromBundles:nil 来进行模板文件的读取 如果传值为nil则系统默认会读取所有的实体模板内容到一个数据库中。如果涉及多个功能模块和多个实体的话就需要使用NSManagedObjectModel类的对象方法initWithContentsOfURL:此方法的URL包装的地址必须是模板文件所在的地址具体方法如下:
NSURL *companyURL = [[NSBundlemainBundle] URLForResource:modelNamewithExtension:@"momd"];
NSManagedObjectModel *model = [ [NSManagedObjectModelalloc] initWithContentsOfURL:companyURL];
如果想查看此模板文件则使用NSLog(@"Bundle Path= %@", [[NSBundle mainBundle] bundlePath]);即可打开包所在的文件夹再右键——>显示包内容 带有.momd后缀类型的文件就是存放对应实体模板内容的东西。第四步:拼接数据库的绝对路径(加数据库后缀名)一般数据库都存放在沙盒的Document路径下,而数据库名都为"模板名.sqlite",具体实现如下:
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject];
NSString *sqliteName = [NSStringstringWithFormat:@"%@.sqlite", modelName];
NSString *sqlitePath = [docstringByAppendingPathComponent:sqliteName];
NSLog(@"%@", sqlitePath);
第五步:以NSManagedObjectModel对象为参数初始化生成一个持久化存储助理类NSPersistentStoreCoordinator的对象,并使用addPersistentStoreWithType 方法为其指定持久化文件的类型(一般都是数据库类型(NSSQLiteStoreType))和创建好的数据库路径,具体实现如下:
NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinatoralloc] initWithManagedObjectModel:model];
[store addPersistentStoreWithType:NSSQLiteStoreTypeconfiguration:nilURL:[NSURLfileURLWithPath:sqlitePath] options:nilerror:nil];
第六步:创建上下文NSManagedObjectContext的对象,并为其persistentStoreCoordinator属性指定为创建好的持久化存储助理对象。并将上下文对象返回给对应的全局上下文变量。具体实现如下:
NSManagedObjectContext *context = [[NSManagedObjectContextalloc] init];
context.persistentStoreCoordinator = store;
新建工程,具体步骤如下:步骤一:新增weibo模板,并为其添加实体设置属性。如下图:
步骤二:为新模块自动生成模块内对应的实体类。
步骤三:打印Bundle的路径 打开路径后 右键—>包内容 查看生成的momd文件(存放对应实体模板的内容)。如下图:
步骤四:卸载程序重新加载运行,打开数据库路径文件夹,查看生成的数据库和数据库里生成的内容如下图:
工程的具体代码如下:
自动生成的实体类代码如下:
//
// Employee.h
// CoreData的简单使用
//
// Created by apple on 15/11/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class Department;
@interface Employee : NSManagedObject
@property (nonatomic, retain) NSDate * birthday;
@property (nonatomic, retain) NSNumber * height;
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) Department *depart;
@end
Employee.m
//
// Employee.m
// CoreData的简单使用
//
// Created by apple on 15/11/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "Employee.h"
#import "Department.h"
@implementation Employee
@dynamic birthday;
@dynamic height;
@dynamic name;
@dynamic depart;
@end
Department.h
//
// Department.h
// CoreData的简单使用
//
// Created by apple on 15/11/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Department : NSManagedObject
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * departNo;
@property (nonatomic, retain) NSDate * createDate;
@end
Department.m
//
// Department.m
// CoreData的简单使用
//
// Created by apple on 15/11/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "Department.h"
@implementation Department
@dynamic name;
@dynamic departNo;
@dynamic createDate;
@end
Status.h
//
// Status.h
// CoreData的简单使用
//
// Created by apple on 15/11/3.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface Status : NSManagedObject
@property (nonatomic, retain) NSString * text;
@property (nonatomic, retain) NSDate * createDate;
@end
Status.m
//
// Status.m
// CoreData的简单使用
//
// Created by apple on 15/11/3.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
#import "Status.h"
@implementation Status
@dynamic text;
@dynamic createDate;
@end
手动编辑的控制器代码如下:
//
// ViewController.m
// CoreData的简单使用
//
// Created by apple on 15/11/2.
// Copyright (c) 2015年 LiuXun. All rights reserved.
//
/**
一个数据库对应一个上下文
如果涉及多个功能模块的话,一般都是一个模块对应一个实体模板,一个实体模板对应一个上下文和数据库
*/
#import "ViewController.h"
#import "Employee.h"
#import "Status.h"
#import "Department.h"
#import <CoreData/CoreData.h>
@interface ViewController ()
@property(nonatomic, strong)NSManagedObjectContext *modelContext;
@property(nonatomic, strong)NSManagedObjectContext *weiboContext;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 在实际开发中,一般一个数据库对应一个上下文。
self.modelContext = [self setUpContextWithModelName:@"Model"];
self.weiboContext = [self setUpContextWithModelName:@"Weibo"];
[self addEmployee];
}
-(NSManagedObjectContext *)setUpContextWithModelName:(NSString *)modelName
{
/**
1. 创建模型文件(相当于数据库里的一张关系表)
2. 添加实体(与一个对象相对应)
3. 创建实体类(相当于模型)
4. 生成上下文 关联模型文件生成数据库
: 注意:关联的时候,如果本地没有数据库文件,coreData自己会创建。
*/
// 在实际开发中,一般一个数据库对应一个上下文。
// 上下文是专门用来管理实体对象的
NSManagedObjectContext *context = [[NSManagedObjectContext alloc] init];
// 关联数据库——参数传为nil,意味着从所有的模板xcdatamodeld进行读取
// 如果参数bundles为nil 会把bundles里面的所有模型文件的表放在一个数据库。
// NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
// NSLog(@"Bundle Path= %@", [[NSBundle mainBundle] bundlePath]);
// 根据具体指定的模板文件建立对应的数据库
NSURL *companyURL = [[NSBundle mainBundle] URLForResource:modelName withExtension:@"momd"];
NSManagedObjectModel *model = [ [NSManagedObjectModel alloc] initWithContentsOfURL:companyURL];
// 持久化存储助理(调度器)
// 持久化,把数据保存到一个文件里,而不是内存
NSPersistentStoreCoordinator *store = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 告诉Coredata数据库的名称和路径
NSString *doc = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
NSString *sqliteName = [NSString stringWithFormat:@"%@.sqlite", modelName];
NSString *sqlitePath = [doc stringByAppendingPathComponent:sqliteName];
NSLog(@"%@", sqlitePath);
[store addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqlitePath] options:nil error:nil];
context.persistentStoreCoordinator = store;
return context;
}
#pragma mark 添加员工
-(void)addEmployee
{
Employee *emp = [NSEntityDescription insertNewObjectForEntityForName:@"Employee" inManagedObjectContext:self.modelContext];
emp.name = @"张三";
emp.height = @(2.3);
emp.birthday = [NSDate date];
NSError *error;
[self.modelContext save:&error];
if (error) {
NSLog(@"%@", [error localizedDescription]);
}
// 发微博
Status *status = [NSEntityDescription insertNewObjectForEntityForName:@"Status" inManagedObjectContext:self.weiboContext];
status.text = @"快工作了,很期待高工资";
status.createDate = [NSDate date];
[self.weiboContext save:nil];
}
@end
需要注意的是:有多个模块对应多个上下文全局变量,每一个上下文对应每一个实体模板和一个数据库。当我们对实体进行具体操作时传入上下文时不要传错,另外就是对从数据库取出数据对象进行修改保存时使用的上下文对象也必须是与数据库对应的上下文对象 否则不会起作用。