zoukankan      html  css  js  c++  java
  • Coredata — 入门使用

    CoreData的底层实现尽管是使用的sqlite数据库。但是CoreData在使用起来但是和sqlite大相径庭。可能你会发现你连一句sql语句都不要写。CoreData存在于应用程序和持久化存储区之间,扮演了桥梁的角色,将托管的对象映射到持久化存储区其中。

    1.设置上下文

    在代码開始之前还须要加入CoreData框架,并在合适的地方引入头文件<CoreData/CoreData.h>:

    QQ20160122-1

    1. // 从应用程序包中载入模型文件
    2. NSManagedObjectModel *model = [NSManagedObjectModel mergedModelFromBundles:nil];
    3. // 传入模型对象。初始化NSPersistentStoreCoordinator
    4. NSPersistentStoreCoordinator *psc = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
    5. // 构建SQLite数据库文件的路径
    6. NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"model.data"];
    7. // 将数据库路径转成URL
    8. NSURL *url = [NSURL fileURLWithPath:filePath];
    9. // 加入持久化存储库,这里使用SQLite作为存储库
    10. NSError *error = nil;
    11. NSPersistentStore *store = [psc addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:url options:nil error:&error];
    12. // 推断数据库是否加入成功
    13. if (store == nil) {
    14. [NSException raise:@"加入数据库错误" format:@"%@", [error localizedDescription]];
    15. }
    16. // 初始化上下文
    17. NSManagedObjectContext *context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    18. // 设置persistentStoreCoordinator属性
    19. context.persistentStoreCoordinator = psc;

    2.加入数据

    1. // 创建一个Husband实体对象,传入上下文
    2. NSManagedObject *husband = [NSEntityDescription insertNewObjectForEntityForName:@"Husband" inManagedObjectContext:context];
    3. // 通过键值编码的方式设置Husband的name属性
    4. [husband setValue:@"jack" forKey:@"name"];
    5. // 通过coredata生成的实体类来创建一个Wife实体对象,传入上下文
    6. Wife *wife = [NSEntityDescription insertNewObjectForEntityForName:@"Wife" inManagedObjectContext:context];
    7. // 通过setter方法设置属性
    8. wife.name = @"rose";
    9. // 设置Husband和Wife之间的关联关系(一方关联,还有一方自己主动关联)
    10. wife.husband = husband;
    11. // 利用上下文对象,将数据同步到持久化存储库
    12. BOOL success = [context save:&error];
    13. if (!success) {
    14. [NSException raise:@"訪问数据库错误" format:@"%@", [error localizedDescription]];
    15. }
    16. // 假设是想做更新操作:须要将实体对象先查询出来。在更改了实体对象的属性后调用[context save:&error],就能将更改的数据同步到数据库

     3.查询数据

    1. // 初始化一个查询请求
    2. NSFetchRequest *request = [[NSFetchRequest alloc] init];
    3. // 设置要查询的实体
    4. request.entity = [NSEntityDescription entityForName:@"Husband" inManagedObjectContext:context];
    5. // 设置排序(依照name降序)
    6. NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:NO];
    7. request.sortDescriptors = [NSArray arrayWithObject:sort];
    8. // 设置条件过滤(搜索name中包括字符串"ja"的记录)
    9. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like %@", @"*ja*"];
    10. request.predicate = predicate;
    11. // 运行请求,返回一个数组
    12. NSArray *objs = [context executeFetchRequest:request error:&error];
    13. if (error) {
    14. [NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];
    15. }
    16. // 遍历数据
    17. for (NSManagedObject *obj in objs) {
    18. NSLog(@"name=%@", [obj valueForKey:@"name"]);
    19. // 实体属性中包括还有一个实体。不须要再次设置查询请求,Core Data会依据关联关系查询到关联的实体信息
    20. NSLog(@"wife = %@", [[obj valueForKey:@"wife"] valueForKey:@"name"]);
    21. }

    fetchRequest相当于sql查询语句的包装类。须要用setEntity方法,来指定详细查询的实体结构(表结构);

    通过NSEntityDescription的entityForName方法来。返回指向该详细实体结构的指针;

    然后调用executeFetchRequest:error:方法,来运行查询操作,假设操作成功,则返回相应的数据记录数组。

    当中,能够通过NSManagedObject数据记录对象里关联的属性,查询还有一个数据记录对象里的属性;

    CoreData不会依据实体中的关联关系马上获取对应的关联对象,比方通过CoreData取出Husband实体时。并不会马上查询相关联的Wife实体;当应用真的须要使用Wife时,才会再次查询数据库。载入Wife实体的信息。这个就是CoreData的延迟载入机制。

    QQ20160122-2

    4.删除数据

    Core Data的增删改使用的方法都是save:方法,在上下文调用save方法之前,全部的数据改动都是发生在内存中的。仅仅有调用save方法后,上下文中发生的数据改动才会被写入到持久化存储区。

    获取到须要删除的实体对象之后。调用deleteObject:方法就能够从上下文中删除这个实体对象了,最后须要调用save:方法同步改动到数据库中:

    1. // 初始化一个查询请求
    2. NSFetchRequest *request = [[NSFetchRequest alloc] init];
    3. // 设置要查询的实体
    4. request.entity = [NSEntityDescription entityForName:@"Husband" inManagedObjectContext:context];
    5. // 设置条件过滤(搜索name等于jack2的实体)
    6. NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name == %@", @"jack2"];
    7. request.predicate = predicate;
    8. // 运行请求,返回一个数组
    9. NSArray *objs = [context executeFetchRequest:request error:&error];
    10. if (error) {
    11. [NSException raise:@"查询错误" format:@"%@", [error localizedDescription]];
    12. }
    13. // 遍历数据
    14. for (NSManagedObject *obj in objs) {
    15. // 传入须要删除的实体对象
    16. [context deleteObject:obj];
    17. // 将结果同步到数据库
    18. [context save:&error];
    19. if (error) {
    20. [NSException raise:@"删除错误" format:@"%@", [error localizedDescription]];
    21. }
    22. }

    5.新建project时勾选Use Core Data选项的情况

    在新建project时使用CoreData,系统会帮我们在AppDelegate中搭建好一个上下文环境,我们能够在其它的controller中去使用这个context,省去了自己搭建上下文的操作,使用起来很简便。

    AppDelegate.h中:

    1. @interface AppDelegate : UIResponder
    2.  
    3. @property (strong, nonatomic) UIWindow *window;
    4.  
    5. // 搭建上下文环境须要使用的对象
    6. @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
    7. @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
    8. @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
    9.  
    10. // 保存实体对象到数据库中
    11. - (void)saveContext;
    12. // 取得程序沙盒路径的URL
    13. - (NSURL *)applicationDocumentsDirectory;
    14.  
    15.  
    16. @end

    AppDelegate.m中:

    1. #pragma mark - Core Data stack
    2.  
    3. @synthesize managedObjectContext = _managedObjectContext;
    4. @synthesize managedObjectModel = _managedObjectModel;
    5. @synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
    6.  
    7. - (NSURL *)applicationDocumentsDirectory {
    8. // The directory the application uses to store the Core Data store file. This code uses a directory named "edu.hcit.qqqqq" in the application's documents directory.
    9. return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
    10. }
    11.  
    12. - (NSManagedObjectModel *)managedObjectModel {
    13. // 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.
    14. if (_managedObjectModel != nil) {
    15. return _managedObjectModel;
    16. }
    17.  
    18. /**************************************************************************************************/
    19. // model 是模型文件的名称,默认是和项目名称同样的
    20. NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"model" withExtension:@"momd"];
    21. _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    22. return _managedObjectModel;
    23. }
    24.  
    25. - (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    26. // The persistent store coordinator for the application. This implementation creates and returns a coordinator, having added the store for the application to it.
    27. if (_persistentStoreCoordinator != nil) {
    28. return _persistentStoreCoordinator;
    29. }
    30. // Create the coordinator and store
    31. _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    32. /**************************************************************************************************/
    33. // 以下的数据库 model.sqlite 是存储实体数据的数据库
    34. NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"model.sqlite"];
    35. NSError *error = nil;
    36. NSString *failureReason = @"There was an error creating or loading the application's saved data.";
    37. if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
    38. // Report any error we got.
    39. NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    40. dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
    41. dict[NSLocalizedFailureReasonErrorKey] = failureReason;
    42. dict[NSUnderlyingErrorKey] = error;
    43. error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
    44. // Replace this with code to handle the error appropriately.
    45. // 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.
    46. NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    47. abort();
    48. }
    49. return _persistentStoreCoordinator;
    50. }
    51.  
    52.  
    53. - (NSManagedObjectContext *)managedObjectContext {
    54. // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.)
    55. if (_managedObjectContext != nil) {
    56. return _managedObjectContext;
    57. }
    58. NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
    59. if (!coordinator) {
    60. return nil;
    61. }
    62. _managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
    63. [_managedObjectContext setPersistentStoreCoordinator:coordinator];
    64. return _managedObjectContext;
    65. }
    1. #pragma mark - Core Data Saving support
    2.  
    3. - (void)saveContext {
    4. NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
    5. if (managedObjectContext != nil) {
    6. NSError *error = nil;
    7. if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
    8. // Replace this implementation with code to handle the error appropriately.
    9. // 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.
    10. NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
    11. abort();
    12. }
    13. }
    14. }

    假设在一个已有的project中加入CoreData。搭建上下文时能够新建一个使用CoreData的project,将上述的代码复制到已有project,在AppDelegate.m中将模型文件的名称和数据库名称稍作改动就可以。数据的操作方法与上文类似。

    6.打印隐藏的SQL语句

    在Edit Scheme中选择Run,之后进入Arguments标签,加入參数:“-com.apple.CoreData.SQLDebug 1”

    屏幕快照 2016-01-22 下午4.35.09

    QQ20160122-9

    打开SQL语句隐藏开关后,程序在执行时。debug日志里会打印程序执行的SQL语句:

    QQ20160122-3

  • 相关阅读:
    8.5
    8.12
    8.11
    8.14
    8.15
    8.18
    8.16
    8.20
    Android新版NDK环境配置(免Cygwin)
    在Windows7上搭建Cocos2d-x win32开发环境
  • 原文地址:https://www.cnblogs.com/gccbuaa/p/7351027.html
Copyright © 2011-2022 走看看