ios coredate使用(下篇)

本篇主要讲述一些细枝末节的知识点。


建模

属性和关系

在XCode中,建模时就可以添加属性和标识实体间的相互关系。具体参见下图,下面还有对应说明:



  1. Entities中列举了实体的列表;
  2. 每个Entity的属性列表在Attributes中,注意Attributes可以多选之后在右边一起改属性类型;
  3. 通过添加关系可以标识出两种不同类型的Entity之间的相互联系;
  4. 每个Relationship都是可以编辑的,主要侧重于一对一还是多对一的关系描述;在我们这个例子中,我们在Employer中设置一对一的关系,然后在Company中选择"To-Many Relationship"选项,使得Company与Employer变成一对多的关系;
  5. 编辑完相互关系后,在Inverse中设置一下,使两者的关系变成真正的关联关系,而不是孤立的联系(这个可以选择Editor Style为table看到两者区别),到这里是不是和Hibernate有点类似了微笑

创建NSManagedObject类的子类

好处——类型校验

创建NSManagedObject类的子类的对象的好处是你可以不用如下的代码(很明显如下的代码是没有类型校验的):

[cpp]  view plain copy
  1. NSManagedObject *event = [NSEntityDescription insertNewObjectForEntityForName:@"Event" inManagedObjectContext:managedObjectContext];  
  2. [event setValue:[NSDate date] forKey:@"creationDate"];  

步骤

  1. 选中.xcdatamodeld这个模型文件;
  2. 选中一个实体;
  3. 从菜单中选择Editor->Create NSManagedObject class,可以创建需要的子类;




取回数据

注意fetch data的时候实际上可以直接使用code snippet,如下:



使用断言

使用断言可以用来筛选我们取出的数据,所以我们的代码可能是这样,同样可以使用code snippet:

[cpp]  view plain copy
  1. -(void)loadData  
  2. {  
  3.     // Create the Request  
  4.     NSFetchRequest *request = [[NSFetchRequest alloc] init];  
  5.     NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:managedObjectContext];  
  6.     [request setEntity:entity];  
  7.     // Set the Sort Descriptor  
  8.     NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"creationDate" ascending:NO];  
  9.     NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];  
  10.     [request setSortDescriptors:sortDescriptors];  
  11.     // Create Predicate  
  12.     // equal  
  13. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description == 'Tom's birthday'"];  
  14. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description == [c]'tom's birthday'"];  
  15.     // like  
  16. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description LIKE 'Tom*'"];  
  17. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description LIKE [cd]'Tom*'"];  
  18. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description LIKE '*om*'"];  
  19.     // begins  
  20. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description BEGINSWITH 'TOM'"];  
  21.     // date  
  22. //    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"createDate < %@", [NSDate date]];  
  23.     // and  
  24.     NSPredicate *predicate = [NSPredicate predicateWithFormat:@"description BEGINSWITH 'TOM' AND createDate < %@", [NSDate date]];  
  25.     [request setPredicate:predicate];  
  26.       
  27.     // Execute the Request  
  28.     NSError *error = nil;  
  29.     NSMutableArray *mutableFetchResults = [[managedObjectContext executeFetchRequest:request error:&error] mutableCopy];  
  30.     if (mutableFetchResults == nil) {  
  31.         // Handle the error.  
  32.         NSLog(@"error loading data");  
  33.     }  
  34.     // Finish Up  
  35.     [self setEventsArray:mutableFetchResults];  
  36. }  

创建带断言的fetching request templete

创建模板的好处是XCode本身提供了一个编辑器,这样就不需要我们自己编写这部分断言代码,而是可以使用图形化的方式编辑我们的条件,而且便于我们管理这部分代码。

  1. 我们选择模型文件,然后去菜单,选择Editor->Add Fetch Request:


  2. 进入之后的页面中我们可以编辑我们的条件,并且可以切换图形和代码方式查看:


  3. 编辑完条件后,我们的代码变更为:
    [cpp]  view plain copy
    1. // Create Fetch Request  
    2. NSFetchRequest *fetchRequest = [[self managedObjectModel] fetchRequestTemplateForName:@"EssentialCourses"];  
    3.   
    4. // Create Sort Descriptor  
    5. NSSortDescriptor *sort = [[NSSortDescriptor alloc]initWithKey:@"releaseDate" ascending:YES];  
    6. NSArray *sortDescriptors = [[NSArray alloc]initWithObjects:sort, nil];  
    7. [fetchRequest setSortDescriptors:sortDescriptors];  
    8.   
    9. NSError *error = nil;  
    10. NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];  
    11. if (fetchedObjects == nil) {  
    12.     NSLog(@"Problem! %@",error);  
    13. }  
    14.   
    15. for (Course *c in fetchedObjects) {  
    16.     NSLog(@"Course: %@ by author: %@", c.title, c.author);  
    17. }  

  4. 运行,查看效果。


版本管理

数据不能兼容

对于数据不能兼容的情况,我们在AppDelegate中做如下处理:

[cpp]  view plain copy
  1. - (NSPersistentStoreCoordinator *)persistentStoreCoordinator  
  2. {  
  3.     if (_persistentStoreCoordinator != nil) {  
  4.         return _persistentStoreCoordinator;  
  5.     }  
  6.       
  7.     NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataCourse.sqlite"];  
  8.       
  9.     NSError *error = nil;  
  10.     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];  
  11.     if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {  
  12.         // delete record  
  13.         [[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];  
  14.         NSLog(@"Unresolved error %@, %@", error, [error userInfo]);  
  15.         abort();  
  16.     }      
  17.       
  18.     return _persistentStoreCoordinator;  
  19. }  

注意其中的removeItemAtURL。


向前兼容

为了数据能够向前兼容老版本,你需要做如下工作:

  1. 创建实体的新版本;

  2. 新实体创建后会出现如下图的对应model文件:


  3. 去编辑新的实体;

  4. 选中.cxdatemodelId,在右边的属性中选择激活的模型版本;

  5. 修改代码,注意新增加的options:
    [cpp]  view plain copy
    1. - (NSPersistentStoreCoordinator *)persistentStoreCoordinator  
    2. {  
    3.     if (_persistentStoreCoordinator != nil) {  
    4.         return _persistentStoreCoordinator;  
    5.     }  
    6.       
    7.     NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"CoreDataCourse.sqlite"];  
    8.       
    9.     NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithBool:YES],NSMigratePersistentStoresAutomaticallyOption, [NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption, nil];  
    10.   
    11.       
    12.     NSError *error = nil;  
    13.     _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];  
    14.     if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {  
    15.         NSLog(@"Unresolved error %@, %@", error, [error userInfo]);  
    16.         abort();  
    17.     }      
    18.       
    19.     return _persistentStoreCoordinator;  
    20. }  

  6. 这里还是描述的简单情况,实际的版本管理和数据合并更加复杂,您可能需要参考:https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/CoreDataVersioning/Articles/Introduction.html


尾声

到这里基本上Core Data相关的功能已经介绍完了,整体上看下来Core Data的学习曲线还是蛮陡峭的,但是基本的使用非常简单,建议大家在工作中逐步摸索。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值