编写Core Data代码
在前面创建Data Model的过程中,我们已经创建3个被管理对象(NSManagedObject),也就是实体对象。
这里,我们创建其他Data Core框架中的对象,启用Core Data数据持久化存储功能。
打开项目中的CartAppDelegate.h文件,添加NSManagedObjectContext属性和2个方法的原型定义。更新后的代码如下所示:
#import <UIKit/UIKit.h>
@interface CartAppDelegate : UIResponder
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
- (void) insertDataIntoShoppingCartDB;
- (void) displayShoppingCart;@end
打开 CartAppDelegate.m 文件,添加managedObjectContext属性的@synthesize编译指令。
@synthesize managedObjectContext = _managedObjectContext;
进一步实现managedObjectContext 实例变量的初始化方法。这段代码理稍微有点难理解。下面解释一下,首先获取存储文件(或数据库文件)存放位置,这里设置为App的Document目录下,存储文件(或数据库文件)为ShoppingCar Database。
然后,创建NSPersistentStoreCoordinator 对象,指定存储类型(SQLite数据库)和存储路径。最后,实例化被管理对象上下文(Managed Object Context),并赋值其持久化存储协调器。- (NSManagedObjectContext *) managedObjectContext{
if(_managedObjectContext == nil){
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory
inDomains:NSUserDomainMask] lastObject];
NSURL *storeDatabaseURL = [url URLByAppendingPathComponent:@"ShoppingCart.sqlite"];
// 设置SQLite 数据库存储路径 /ShoppingCart.sqlite
NSError *error = nil;
//根据被管理对象模型创建NSPersistentStoreCoordinator 对象实例
NSPersistentStoreCoordinator *persistentStoreCoordinator =
[[NSPersistentStoreCoordinator alloc]
initWithManagedObjectModel:[NSManagedObjectModel mergedModelFromBundles:nil]];
//根据指定的存储类型和路径,创建一个新的持久化存储(Persistent Store)
if(![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeDatabaseURL options:nil error:&error])
{
NSLog(@"Error while loading persistent store ...%@", error);
}
_managedObjectContext = [[NSManagedObjectContext alloc] init];
//设置当前被管理对象上下文的持久化存储协调器
[_managedObjectContext setPersistentStoreCoordinator:persistentStoreCoordinator]; }
// 返回初始化的被管理对象上下文实例
return _managedObjectContext;
}
在CartAppDelegate.m文件实现接口中定义的insertDataIntoShoppingCartDB 方法,该方法主要是箱SQLite数据库中插入一些初始数据,供测试用途。
下面的代码,实现向Customer、ShoppingCartMaster和ShoppingCartDetail三个实体中插入初始化数据。// 向SQLite插入一些初始数据
- (void) insertDataIntoShoppingCartDB{
// 创建Customer 被管理对象实例
Customer *customer1 = (Customer *)[NSEntityDescription insertNewObjectForEntityForName:@"Customer"
inManagedObjectContext:self.managedObjectContext];
customer1.customerID = [NSNumber numberWithInt:1];
customer1.customerName = @"客户姓名-笨笨";
customer1.password = @"EntLib.com";
customer1.userName = @"EntLib.com";
// 创建ShoppingCartMaster 被管理对象实例
ShoppingCartMaster *shoppingCartMaster1 = (ShoppingCartMaster *)[NSEntityDescription
insertNewObjectForEntityForName:@"ShoppingCartMaster" inManagedObjectContext:self.managedObjectContext];
shoppingCartMaster1.cartID = [NSNumber numberWithInt:100];
shoppingCartMaster1.customerID = [NSNumber numberWithInt:1];
// 创建ShoppingCartDetail 被管理对象实例
ShoppingCartDetail *shoppingCartDetail1= (ShoppingCartDetail *)[NSEntityDescription
insertNewObjectForEntityForName:@"ShoppingCartDetail" inManagedObjectContext:self.managedObjectContext];
shoppingCartDetail1.cartID = [NSNumber numberWithInt:100];
shoppingCartDetail1.currentPrice = [NSDecimalNumber decimalNumberWithDecimal:
[[NSNumber numberWithFloat:18.5f] decimalValue]];
shoppingCartDetail1.productID = @"1-111-111";
shoppingCartDetail1.productName= @"Hello Kitty - iPhone 5 手机";
shoppingCartDetail1.productSysNo = [NSNumber numberWithInt:10];
ShoppingCartDetail *shoppingCartDetail2= (ShoppingCartDetail *)[NSEntityDescription
insertNewObjectForEntityForName:@"ShoppingCartDetail" inManagedObjectContext:self.managedObjectContext];
shoppingCartDetail2.cartID = [NSNumber numberWithInt:100];
shoppingCartDetail2.currentPrice = [NSDecimalNumber decimalNumberWithDecimal:
[[NSNumber numberWithFloat:18.5f] decimalValue]];
shoppingCartDetail2.productID = @"2-222-111";
shoppingCartDetail2.productName= @"Hello Kitty - iPad 3 平板电脑";
shoppingCartDetail2.productSysNo = [NSNumber numberWithInt:10];
// 赋值关系属性实例变量
// 开发测试的时候,可以把下面的代码注释掉,分析比较一下
customer1.cart = shoppingCartMaster1;
[shoppingCartMaster1 addDetailObject:shoppingCartDetail1];
[shoppingCartMaster1 addDetailObject:shoppingCartDetail2];
// 保存数据,持久化存储 SQLite数据库
// 开发测试的时候,可以把下面的代码注释掉,分析比较一下
/*if([self.managedObjectContext hasChanges]){
[self.managedObjectContext save:nil];
}*/}
注意,上面的代码中,我们把向SQLite数据库写入数据的save操作注释了。这个只是在测试过程中,避免反复向数据库中插入初始数据。如果将上述代码注释去掉,就可以实现向SQLite数据库中存储数据。
继续在CartAppDelegate.m文件中实现接口中定义的displayShoppingCart方法。该方法用来在Xcode的调试窗口输出被管理对象上下文中的实体数据。
// 显示SQLite 数据库,购物车中的内容- (void) displayShoppingCart{
// NSFetchRequest 对象用来检索数据
NSFetchRequest *request = [[NSFetchRequest alloc] init];
// 根据指定Entity名称和被管理对象上下文,创建NSEntityDescription对象,
NSEntityDescription *myEntityQuery = [NSEntityDescription
entityForName:@"Customer"
inManagedObjectContext:self.managedObjectContext];
// 指定实体
[request setEntity:myEntityQuery];
NSError *error = nil;
// 返回符合查询条件NSFetchRequest的记录数组
NSArray * customerArr = [self.managedObjectContext executeFetchRequest:request error:&error];
NSInteger recordCount = [customerArr count];
NSLog(@"Record Count: %d", recordCount);
for (int i=0; i< recordCount; i++){
// 数组中元素为Customer 被管理对象
Customer *customer = (Customer *)[customerArr objectAtIndex:i];
NSLog(@"CustomerName: %@", customer.customerName);
// 获取Customer 对应关系的ShoppingCartMaster 对象,一对一关系
ShoppingCartMaster *cart = customer.cart;
NSLog(@"我的购物车: %@", cart.cartID);
// 获取ShoppingCartMaster对象中所有的detail 对象数组,一对多关系
NSArray *productList = [cart.detail allObjects];
int numberOfProducts = [productList count];
NSLog(@"购物车商品数:%d", numberOfProducts);
// 遍历ShoppingCartDetail 数组
for(int i=0; i< numberOfProducts; i++){
ShoppingCartDetail *detail = [productList objectAtIndex:i];
NSLog(@"购物车商品:%@", detail.productName);
}
}
}
注意,这里我们使用被管理对象上下文(Managed Object Context)中获取数据的,也就是在内存中获取数据,因此前面insertDataIntoShoppingCartDB方法中的[self.managedObjectContext save:nil] 代码行,即使注释,也可以获得返回结果。
最后,我们还需要修改CartAppDelegate.m文件中的application:didFinishLaunchingWithOptions:方法中的代码。更新后的代码如下,主要是添加对我们前面定义的2个方法的调用。- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self insertDataIntoShoppingCartDB];
[self displayShoppingCart];
return YES;
}
至于application:didFinishLaunchingWithOptions: 方法在什么时候调用的?
这里,我们需要简单介绍一下iOS应用程序的生命周期。
iOS应用程序的生命周期
在我们创建应用程序时,在项目的Supporting Files 文件夹中,自动创建了main.m文件。
main.m 是程序的入口,我们看一下main.m文件的代码。
#import <UIKit/UIKit.h>
#import "CartAppDelegate.h"
int main(int argc, char *argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([CartAppDelegate class]));
}
}
在main中执行一个方法UIApplicationMain,该方法返回一个UIApplicationMain对象表示我们的这个应用程序对象。
第四个参数是一个字符串,就是应用程序委托类CartAppDelegate,这个也是在创建项目过程中,Xcode自动创建的。
前面我们修改的application:didFinishLaunchingWithOptions: 方法就在这个类中,iOS程序启动时总会调用此方法。
——
未完待续!!!