本人ios初學(xué)者,為自己學(xué)習(xí)方便,復(fù)制各位大神的學(xué)習(xí)性文章放在自己簡(jiǎn)書里,僅作為自己學(xué)習(xí)方便使用,如果作者疑此行為侵權(quán),請(qǐng)隨時(shí)聯(lián)系本人刪除,如有共同學(xué)習(xí)者復(fù)制此文章,請(qǐng)注明原出處
http://www.th7.cn/Program/IOS/201506/490903.shtml
Core Date是ios3.0后引入的數(shù)據(jù)持久化解決方案,它是是蘋果官方推薦使用的,不需要借助第三方框架。Core Date實(shí)際上是對(duì)SQLite的封裝,提供了更高級(jí)的持久化方式。在對(duì)數(shù)據(jù)庫(kù)操作時(shí),不需要使用sql語(yǔ)句,也就意味著即使不懂sql語(yǔ)句,也可以操作數(shù)據(jù)庫(kù)中的數(shù)據(jù)?! ≡诟黝悜?yīng)用開發(fā)中使用數(shù)據(jù)庫(kù)操作時(shí)通常都會(huì)用到 (ORM) “對(duì)象關(guān)系映射”,Core Data就是這樣的一種模式。ORM是將關(guān)系數(shù)據(jù)庫(kù)中的表,轉(zhuǎn)化為程序中的對(duì)象,但實(shí)際上是對(duì)數(shù)據(jù)中的數(shù)據(jù)進(jìn)行操作。 在使用Core Data進(jìn)?行數(shù)據(jù)庫(kù)存取并不需要手動(dòng)創(chuàng)建數(shù)據(jù)庫(kù),創(chuàng)建數(shù)據(jù)庫(kù)的過(guò)程完全由Core Data框架自動(dòng)完成,開發(fā)者需要做的就是把模型創(chuàng)建起來(lái),具體數(shù)據(jù)庫(kù)的創(chuàng)建不需要管。簡(jiǎn)單點(diǎn)說(shuō),Core Data實(shí)際上是將數(shù)據(jù)庫(kù)的創(chuàng)建、表的創(chuàng)建、對(duì)象和表的轉(zhuǎn)換等操作封裝起來(lái),極大的簡(jiǎn)化了我們的操作?! ore Date與SQLite相比較,SQLite比較原始,操作比較復(fù)雜,使用的是C的函數(shù)對(duì)數(shù)據(jù)庫(kù)進(jìn)行操作,但是SQLite可控性更強(qiáng),并且能夠跨平臺(tái)?! ∠旅妫屛覀円黄饋?lái)學(xué)習(xí)一下Core Data的簡(jiǎn)單使用。一、使用Core Data,添加實(shí)體和模型 在創(chuàng)建項(xiàng)目的時(shí)候可以選擇使用Core Data,項(xiàng)目創(chuàng)建成功后,會(huì)在AppDelegate類中自動(dòng)添加相關(guān)代碼,此外,還會(huì)自動(dòng)生成一個(gè)數(shù)據(jù)模型文件JRCoreData.xcdatamodeld AppDelegate.h//? AppDelegate.h//? JRCoreData////? Created by jerei on 15-6-24.//? Copyright (c) 2015年 jerehedu. All rights reserved.//#import#import@interface AppDelegate : UIResponder@property (strong, nonatomic) UIWindow *window;@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;- (void)saveContext;- (NSURL *)applicationDocumentsDirectory;@end
AppDelegate.m
//? AppDelegate.m//? JRCoreData////? Created by jerei on 15-6-24.//? Copyright (c) 2015年 jerehedu. All rights reserved.//#import "AppDelegate.h"@interface AppDelegate ()@end@implementation AppDelegate- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {? ? // Override point for customization after application launch.? ? return YES;}- (void)applicationWillResignActive:(UIApplication *)application {? ? // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.? ? // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.}- (void)applicationDidEnterBackground:(UIApplication *)application {? ? // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.? ? // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.}- (void)applicationWillEnterForeground:(UIApplication *)application {? ? // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.}- (void)applicationDidBecomeActive:(UIApplication *)application {? ? // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.}- (void)applicationWillTerminate:(UIApplication *)application {? ? // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.? ? // Saves changes in the application's managed object context before the application terminates.? ? [self saveContext];}#pragma mark - Core Data stack@synthesize managedObjectContext = _managedObjectContext;@synthesize managedObjectModel = _managedObjectModel;@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;- (NSURL *)applicationDocumentsDirectory {? ? // The directory the application uses to store the Core Data store file. This code uses a directory named "com.jerehedu.JRCoreData" in the application's documents directory.? ? return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];}- (NSManagedObjectModel *)managedObjectModel {? ? // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model.? ? if (_managedObjectModel != nil) {? ? ? ? return _managedObjectModel;? ? }? ? NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"JRCoreData" withExtension:@"momd"];? ? _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];? ? return _managedObjectModel;}- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {? ? // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.? ? if (_persistentStoreCoordinator != nil) {? ? ? ? return _persistentStoreCoordinator;? ? }? ? ? ? // Create the coordinator and store? ? ? ? _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];? ? NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"JRCoreData.sqlite"];? ? NSError *error = nil;? ? NSString *failureReason = @"There was an error creating or loading the application's saved data.";? ? if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {? ? ? ? // Report any error we got.? ? ? ? NSMutableDictionary *dict = [NSMutableDictionary dictionary];? ? ? ? dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";? ? ? ? dict[NSLocalizedFailureReasonErrorKey] = failureReason;? ? ? ? dict[NSUnderlyingErrorKey] = error;? ? ? ? error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];? ? ? ? // Replace this with code to handle the error appropriately.? ? ? ? // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.? ? ? ? NSLog(@"Unresolved error %@, %@", error, [error userInfo]);? ? ? ? abort();? ? }? ? ? ? return _persistentStoreCoordinator;}
- (NSManagedObjectContext *)managedObjectContext {? ? // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)? ? if (_managedObjectContext != nil) {? ? ? ? return _managedObjectContext;? ? }? ? ? ? NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];? ? if (!coordinator) {? ? ? ? return nil;? ? }? ? _managedObjectContext = [[NSManagedObjectContext alloc] init];? ? [_managedObjectContext setPersistentStoreCoordinator:coordinator];? ? return _managedObjectContext;}#pragma mark - Core Data Saving support- (void)saveContext {? ? NSManagedObjectContext *managedObjectContext = self.managedObjectContext;? ? if (managedObjectContext != nil) {? ? ? ? NSError *error = nil;? ? ? ? if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {? ? ? ? ? ? // Replace this implementation with code to handle the error appropriately.? ? ? ? ? ? // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.? ? ? ? ? ? NSLog(@"Unresolved error %@, %@", error, [error userInfo]);? ? ? ? ? ? abort();? ? ? ? }? ? }}@end
如果項(xiàng)目在創(chuàng)建的時(shí)候沒有選擇使用Core Data,但是在后面需要使用,那么需要手動(dòng)的添加AppDelegate中的相關(guān)代碼。此外,還需要手動(dòng)添加一個(gè)Data Model文件
創(chuàng)建Data Model文件時(shí)需要注意,文件名稱要與AppDelegate.m中managedObjectModel方法中提到的文件名稱相匹配。
有了Data Model文件后,就可以在里面添加實(shí)體和關(guān)系,實(shí)際上就是向數(shù)據(jù)庫(kù)中添加表格和建立表格之間的關(guān)聯(lián)。添加實(shí)體如圖所示:
每個(gè)學(xué)生有一個(gè)所在的班級(jí),每個(gè)班級(jí)中有多個(gè)學(xué)生,因此,學(xué)生和班級(jí)之間可以建立關(guān)系。建立關(guān)系如圖所示:
建立關(guān)系之后,可以切換顯示的樣式,以圖表的方式查看實(shí)體之間的關(guān)系,如圖所示:
完成上述步驟,數(shù)據(jù)庫(kù)中表格的創(chuàng)建就已經(jīng)完成,和使用SQLite比較,省略了sql語(yǔ)句以及調(diào)用C函數(shù)操作數(shù)據(jù)庫(kù)的步驟,另外,在創(chuàng)建實(shí)體的時(shí)候不需要設(shè)置主鍵,實(shí)體對(duì)象的屬性的類型是OC的類型,實(shí)體中其他實(shí)體對(duì)象類型是通過(guò)建立關(guān)系添加的。
創(chuàng)建好實(shí)體后,可以通過(guò)添加NSManagedObject subclass文件,系統(tǒng)可以自動(dòng)添加實(shí)體對(duì)應(yīng)的數(shù)據(jù)模型類,如圖所示:
二、通過(guò)代碼實(shí)現(xiàn)數(shù)據(jù)庫(kù)的操作
1、 向?qū)W生表中插入一條數(shù)據(jù)
在使用Core Data的時(shí)候,AppDelegate中添加了NSManagedObjectContext對(duì)象,需要獲得這個(gè)管理對(duì)象的上下文來(lái)進(jìn)行操作。在操作的過(guò)程中,需要得到NSManagedObject實(shí)體,然后通過(guò)kvc設(shè)置實(shí)體的屬性值,最后通過(guò)上下文調(diào)用save方法保存數(shù)據(jù)。
- (void)insert {? ? ? ? AppDelegate *delegate = [[UIApplication sharedApplication] delegate];? ? ? ? //1. 獲得context? ? NSManagedObjectContext *context = delegate.managedObjectContext;? ? //2. 找到實(shí)體結(jié)構(gòu),并生成一個(gè)實(shí)體對(duì)象? ? /*? ? NSEntityDescription實(shí)體描述,也就是表的結(jié)構(gòu)? ? 參數(shù)1:表名字? ? 參數(shù)2:實(shí)例化的對(duì)象由誰(shuí)來(lái)管理,就是context? ? */? ? NSManagedObject *stu = [NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:context];? ? ? ? NSManagedObject *class1 = [NSEntityDescription insertNewObjectForEntityForName:@"Classes" inManagedObjectContext:context];? ? [class1 setValue:[NSNumber numberWithInt:1] forKey:@"c_id"];? ? [class1 setValue:@"一班" forKey:@"c_name"];? ? ? ? //3. 設(shè)置實(shí)體屬性值? ? [stu setValue:[NSNumber numberWithInt:1] forKey:@"s_id"];? ? [stu setValue:@"jerehedu" forKey:@"s_name"];? ? [stu setValue:class1 forKey:@"s_class"];? ? ? ? //4. 調(diào)用context,保存實(shí)體,如果沒有成功,返回錯(cuò)誤信息? ? NSError *error;? ? if ([context save:&error]) {? ? ? ? NSLog(@"save ok");? ? }? ? else? ? {? ? ? ? NSLog(@"%@",error);? ? }}
2、查詢學(xué)生表中全部數(shù)據(jù)
查詢與插入數(shù)據(jù)操作類似,但是多了構(gòu)造查詢對(duì)象的步驟,查詢得到結(jié)果集是一個(gè)數(shù)組,遍歷數(shù)組,可以取出查詢數(shù)據(jù)。
- (void)selectAll {? ? AppDelegate *delegate = [[UIApplication sharedApplication] delegate];? ? ? ? NSManagedObjectContext *context = delegate.managedObjectContext;? ? ? ? NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];? ? ? ? //構(gòu)造查詢對(duì)象? ? NSFetchRequest *request = [[NSFetchRequest alloc] init];? ? [request setEntity:stu];? ? ? ? //執(zhí)行查詢,返回結(jié)果集? ? NSArray *resultAry = [context executeFetchRequest:request error:nil];? ? ? ? //遍歷結(jié)果集? ? for (NSManagedObject *enity in resultAry) {? ? ? ? NSLog(@"id=%i name=%@ class=%@",[[enity valueForKey:@"s_id"] intValue],[enity valueForKey:@"s_name"],[[enity valueForKey:@"s_class"] valueForKey:@"c_name"]);? ? }}
3、查詢指定條件的學(xué)生信息,并更新
指定條件的查詢除了需要構(gòu)造查詢對(duì)象,還需要把查詢的條件用謂詞表示。然后遍歷查詢結(jié)果數(shù)組中的數(shù)據(jù),進(jìn)行更行,并保存。
- (void)update{? ? //? ? 更新 (從數(shù)據(jù)庫(kù)找到-->更新)? ? AppDelegate *delegate = [[UIApplication sharedApplication] delegate];? ? NSManagedObjectContext *context = delegate.managedObjectContext;? ? ? ? NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];? ? ? ? NSFetchRequest *request = [NSFetchRequest new];? ? [request setEntity:stu];? ? ? ? //構(gòu)造查詢條件,相當(dāng)于where子句? ? NSPredicate *predicate = [NSPredicate predicateWithFormat:@"s_id=%i",1];? ? ? ? //把查詢條件放進(jìn)去? ? [request setPredicate:predicate];? ? ? ? //執(zhí)行查詢? ? NSArray *studentAry = [context executeFetchRequest:request error:nil];? ? if (studentAry.count>0)? ? {? ? ? ? //更新里面的值? ? ? ? NSManagedObject *obj = studentAry[0];? ? ? ? [obj setValue:@"apple" forKey:@"s_name"];? ? }? ? [context save:nil];? ? ? ? //顯示? ? [self selectAll];}
4、刪除指定條件的學(xué)生信息
刪除之前首先需要根據(jù)條件進(jìn)行查詢,查詢到數(shù)據(jù)后刪除,并保存。
- (void)delete{? ? //刪除 先找到,然后刪除? ? AppDelegate *delegate = [[UIApplication sharedApplication] delegate];? ? NSManagedObjectContext *context = delegate.managedObjectContext;? ? ? ? NSEntityDescription *stu = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:context];? ? ? ? NSFetchRequest *request = [NSFetchRequest new];? ? [request setEntity:stu];? ? ? ? //構(gòu)造查詢條件,相當(dāng)于where子句? ? NSPredicate *predicate = [NSPredicate predicateWithFormat:@"s_id=%i",1];? ? ? ? //把查詢條件放進(jìn)去? ? [request setPredicate:predicate];? ? //執(zhí)行查詢? ? NSManagedObject *obj = [[context executeFetchRequest:request error:nil] lastObject];? ? //刪除? ? if (obj) {? ? ? ? [context deleteObject:obj];? ? ? ? [context save:nil];? ? }? ? ? ? [self selectAll];}
三、小結(jié)
Core Data是蘋果官方推薦使用的數(shù)據(jù)持久化方式,在使用的過(guò)程中,不需要導(dǎo)入數(shù)據(jù)庫(kù)框架,也不需要使用sql語(yǔ)句操作數(shù)據(jù)庫(kù),完全是按照面向?qū)ο蟮乃枷?,使用?shí)體模型來(lái)操作數(shù)據(jù)庫(kù)。在使用的過(guò)程中需要注意的是,如果模型發(fā)生了變化,可以選擇重新生成實(shí)體類文件,但是自動(dòng)生成的數(shù)據(jù)庫(kù)并不會(huì)自動(dòng)更新,需要考慮重新生成數(shù)據(jù)庫(kù),并把之前數(shù)據(jù)庫(kù)中數(shù)據(jù)進(jìn)行移植。Core Data能夠簡(jiǎn)化操作,但是它不支持跨平臺(tái)使用,如果想實(shí)現(xiàn)跨平臺(tái),就需要使用SQLite來(lái)進(jìn)行數(shù)據(jù)持久化。