編寫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程式啟動時總會調用此方法。
——
未完待續!!!
本教程的具體內容及其範例App都收錄在《一步一步學習iOS 6 編程》的最新版PDF檔案中。