首页 > 代码库 > Core Data with Mantle

Core Data with Mantle

Mantle makes it easy to write a simple model layer for your Cocoa or Cocoa Touch application.  Mantle can still be a convenient translation layer between the API and your managed model objects.

本文使用mantle作data model,并使用其对coredata的interface创建数据持久化的过程。

操作过程很简单,就是数据的转换:


1.Manle data model

Mantle中用于持久化的方法:

// A MTLModel object that supports being serialized to and from Core Data as an

// NSManagedObject.

  • @protocol MTLManagedObjectSerializing
  • @required

// The name of the Core Data entity that the receiver serializes to and

// deserializes from.

  • + (NSString *)managedObjectEntityName;

// Specifies how to map property keys to different keys on the receiver‘s

// +managedObjectEntity.

  • + (NSDictionary *)managedObjectKeysByPropertyKey;

.h 文件

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface BannerWrapper : MTLModel <MTLJSONSerializing,MTLManagedObjectSerializing>  
  4.   
  5. @property (nonatomicreadonlybool result;  
  6. @property (copynonatomicreadonlyNSNumber *resultId;  
  7. @property (copynonatomicreadonlyNSString *resultMsg;  
  8. @property (copynonatomicNSArray *bannerList;  
  9. +(NSSortDescriptor *)sortDescriptor;  
  10. @end  
  11.   
  12. @interface Banner : MTLModel <MTLJSONSerializing, MTLManagedObjectSerializing>  
  13.   
  14. @property (copynonatomicreadonlyNSNumber *bannerId;  
  15. @property (copynonatomicreadonlyNSString *picUrl;  
  16. @property (copynonatomicreadonlyNSString *toDetailUrl;  
  17. @property (copynonatomicreadonlyNSNumber *width;  
  18. @property (copynonatomicreadonlyNSNumber *height;  
  19.   
  20. @end  


.m文件

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import "Banner.h"  
  2.   
  3. @implementation BannerWrapper  
  4.   
  5. #pragma mark - JSON serialization  
  6.   
  7. + (NSDictionary *)JSONKeyPathsByPropertyKey {  
  8.     return @{  
  9.              @"result" : @"result",  
  10.              @"resultId" : @"resultId",  
  11.              @"resultMsg" : @"resultMSG",  
  12.              @"bannerList" : @"banner"  
  13.              };  
  14. }  
  15.   
  16. + (NSValueTransformer *)bannerListJSONTransformer  
  17. {  
  18.     return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:[Banner class]];  
  19. }  
  20.   
  21. #pragma mark - Managed object serialization  
  22.   
  23. + (NSString *)managedObjectEntityName {  
  24.     return @"BannerWrapper";  
  25. }  
  26.   
  27. + (NSDictionary *)managedObjectKeysByPropertyKey {  
  28.     return nil;  
  29. }  
  30.   
  31. +(NSDictionary *)relationshipModelClassesByPropertyKey{  
  32.     return @{  
  33.              @"bannerList"  : [Banner class],  
  34.              };  
  35. }  
  36.   
  37. //在从coredata中取数据时的数据排序方式  
  38. +(NSSortDescriptor *)sortDescriptor{  
  39.     return [[NSSortDescriptor alloc] initWithKey:@"resultId" ascending:YES];  
  40. }  
  41.   
  42. @end  
  43.   
  44. @implementation Banner  
  45.   
  46. #pragma mark - JSON serialization  
  47.   
  48. + (NSDictionary *)JSONKeyPathsByPropertyKey {  
  49.     return @{  
  50.              @"bannerId" : @"id",  
  51.              @"picUrl" : @"picUrl",  
  52.              @"toDetailUrl" : @"toDetailUrl",  
  53.              @"width":@"width",  
  54.              @"height":@"height"  
  55.              };  
  56. }  
  57.   
  58. #pragma mark - Managed object serialization  
  59.   
  60. + (NSString *)managedObjectEntityName {  
  61.     return @"Banner";  
  62. }  
  63.   
  64. + (NSDictionary *)managedObjectKeysByPropertyKey {  
  65.     return nil;  
  66. }  
  67.   
  68. @end  


2.coredata 持久化类

Coredata主要元素简要介绍

网上有很多图,但,还是觉得一本书上的这个图最好:


  • 1, Managed Object Model
    Managed Object Model 是描述应用程序的数据模型,这个模型包含实体(Entity),特性(Property),读取请求(Fetch Request)等。(下文都使用英文术语。)

    2Managed Object Context
    Managed Object Context 参与对数据对象进行各种操作的全过程,并监测数据对象的变化,以提供对 undo/redo 的支持及更新绑定到数据的 UI

    3
    Persistent Store Coordinator
    Persistent Store Coordinator 相当于数据文件管理器,处理底层的对数据文件的读取与写入。一般我们无需与它打交道。

    4Managed Object
    Managed Object 数据对象,与 Managed Object Context 相关联。

  • 5,Controller
    图中绿色的 Array Controller, Object Controller, Tree Controller 这些控制器,一般都是通过 control+drag 将 Managed Object Context 绑定到它们,这样我们就可以在 nib 中可视化地操作数据。

.h文件

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import <Foundation/Foundation.h>  
  2.   
  3. @interface Persistence : NSObject  
  4.   
  5. //数据模型对象  
  6. @property(strong,nonatomicNSManagedObjectModel *managedObjectModel;  
  7. //上下文对象  
  8. @property(strong,nonatomicNSManagedObjectContext *managedObjectContext;  
  9. //持久性存储区  
  10. @property(strong,nonatomicNSPersistentStoreCoordinator *persistentStoreCoordinator;  
  11.   
  12. //确定sqlite文件存储路径  
  13. -(NSURL *)storeURL;  
  14.   
  15. //初始化Core Data使用的数据库  
  16. -(NSPersistentStoreCoordinator *)persistentStoreCoordinator;  
  17.   
  18. //managedObjectModel的初始化赋值函数  
  19. -(NSManagedObjectModel *)managedObjectModel;  
  20.   
  21. //managedObjectContext的初始化赋值函数  
  22. -(NSManagedObjectContext *)managedObjectContext;  
  23.   
  24. //保存MTLModel对象至coredata  
  25. -(BOOL)saveMTLModel:(MTLModel<MTLManagedObjectSerializing> *)mtlModel  
  26.               error:(NSError * __autoreleasing *)error;  
  27.   
  28. //从coredata中提取出MTLModel  
  29. -(MTLModel *)getMTLmodel:(MTLModel<MTLManagedObjectSerializing> *)mtlModel  
  30.                    error:(NSError *__autoreleasing *)error;  
  31.   
  32. //+ (NSFetchRequest *)fetchRequest;  
  33. @end  




.m文件

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. #import "Persistence.h"  
  2.   
  3. @implementation Persistence  
  4.   
  5. @synthesize managedObjectContext;  
  6. @synthesize managedObjectModel;  
  7. @synthesize persistentStoreCoordinator;  
  8.   
  9.   
  10. //确定sqlite文件存储路径  
  11. -(NSURL *)storeURL{  
  12.     //得到数据库的路径  
  13.     //    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];  
  14.     //    //CoreData是建立在SQLite之上的,数据库名称需与Xcdatamodel文件同名  
  15.     //    NSURL *storeUrl = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"CoreData.sqlite"]];  
  16.       
  17.     NSArray *documnetDir=NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);  
  18.     NSString *docDir=[documnetDir objectAtIndex:0];  
  19.     NSString *path=[docDir stringByAppendingPathComponent:@"CoreData.sqlite"];  
  20.     NSURL *storeURL=[NSURL fileURLWithPath:path];  
  21.     return storeURL;  
  22. }  
  23.   
  24.   
  25. //初始化Core Data使用的数据库  
  26. -(NSManagedObjectModel *)managedObjectModel  
  27. {  
  28.     if (managedObjectModel != nil) {  
  29.         return managedObjectModel;  
  30.     }  
  31.     return [NSManagedObjectModel mergedModelFromBundles:nil];  
  32. }  
  33.   
  34. //managedObjectModel的初始化赋值函数  
  35. -(NSPersistentStoreCoordinator *)persistentStoreCoordinator  
  36. {  
  37.     if (persistentStoreCoordinator != nil) {  
  38.         return persistentStoreCoordinator;  
  39.     }  
  40.       
  41.     NSError *error = nil;  
  42.     persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]  
  43.                                   initWithManagedObjectModel:self.managedObjectModel];  
  44.     if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType  
  45.                                                   configuration:nil  
  46.                                                             URL:[self storeURL]  
  47.                                                         options:nil  
  48.                                                           error:&error]) {  
  49.         NSLog(@"Error: %@,%@",error,[error userInfo]);  
  50.         [NSException raise:@"open failed" format:@"Reason:%@",[error localizedDescription]];  
  51.     }  
  52.       
  53.     return persistentStoreCoordinator;  
  54. }  
  55.   
  56. //managedObjectContext的初始化赋值函数  
  57. -(NSManagedObjectContext *)managedObjectContext  
  58. {  
  59.     if (managedObjectContext != nil) {  
  60.         return managedObjectContext;  
  61.     }  
  62.       
  63.     NSPersistentStoreCoordinator *coordinator =self.persistentStoreCoordinator;  
  64.       
  65.     if (coordinator != nil) {  
  66.         managedObjectContext = [[NSManagedObjectContext alloc]init];  
  67.         [managedObjectContext setPersistentStoreCoordinator:coordinator];  
  68.     }  
  69.       
  70.     return managedObjectContext;  
  71. }  
  72.   
  73. //保存MTLModel对象至coredata  
  74. -(BOOL)saveMTLModel:(MTLModel<MTLManagedObjectSerializing> *)mtlModel  
  75.               error:(NSError *__autoreleasing *)error{  
  76.     //-----Need Add Remove the Entity First  START---------  
  77.     NSManagedObject *exsitManagedObject=[self getManagedObject:mtlModel  
  78.                                                          error:error];  
  79.     if (exsitManagedObject!=nil) {  
  80.         [self.managedObjectContext deleteObject:exsitManagedObject];  
  81.         [self.managedObjectContext save:error];  
  82.     };  
  83.     //-----Need Add Remove the Entity First  END-----------  
  84.       
  85.     NSManagedObject *managedObject = [MTLManagedObjectAdapter  
  86.                                       managedObjectFromModel:mtlModel  
  87.                                       insertingIntoContext:self.managedObjectContext  
  88.                                       error:error];  
  89.       
  90.     if (managedObject==nil) {  
  91.         NSLog(@"[NSManagedObject] Error:%@",*error);  
  92.         return NO;  
  93.     }  
  94.       
  95.     if (![self.managedObjectContext save:error]) {  
  96.         NSLog(@"[self.managedObjectContext] Error:%@",*error);  
  97.         return NO;  
  98.     };  
  99.     return YES;  
  100. };  
  101.   
  102. //从coredata中提取出MTLModel  
  103. -(MTLModel *)getMTLmodel:(MTLModel<MTLManagedObjectSerializing> *)mtlModel  
  104.                    error:(NSError *__autoreleasing *)error{  
  105.       
  106.     NSManagedObject *managedObject=[self getManagedObject:mtlModel error:error];  
  107.     MTLModel *mrlMotel=[[MTLModel alloc] init];  
  108.       
  109.     mrlMotel = [MTLManagedObjectAdapter modelOfClass:[mtlModel class]  
  110.                                    fromManagedObject:managedObject error:error];  
  111.       
  112.     if (error) {  
  113.         NSLog(@"[mrlMotel] Error:%@",*error);  
  114.     }  
  115.     return mrlMotel;  
  116. };  
  117.   
  118. //从coredata中获取已存的ManagedObject  
  119. -(NSManagedObject *)getManagedObject:(MTLModel<MTLManagedObjectSerializing> *)mtlModel  
  120.                                error:(NSError *__autoreleasing *)error{  
  121.     NSString *entityName=[[mtlModel class] managedObjectEntityName];  
  122.       
  123.     //获取entity中对象数量  
  124.     NSFetchRequest *requestCount=[NSFetchRequest fetchRequestWithEntityName:entityName];  
  125.     NSUInteger count=[self.managedObjectContext countForFetchRequest:requestCount  
  126.                                                                error:error];  
  127.     NSLog(@"count result:%d",count);  
  128.     NSLog(@"sortDescriptor result:%@",[[mtlModel class] sortDescriptor]);  
  129.       
  130.     //获取entity中第一个对象.这个对象必须存在且唯一。  
  131.     if (count==1) {  
  132.         NSFetchRequest *request=[[NSFetchRequest alloc] init];  
  133.         [request setEntity:[NSEntityDescription entityForName:entityName  
  134.                                        inManagedObjectContext:self.managedObjectContext]];  
  135.         NSSortDescriptor *sort=[[mtlModel class] sortDescriptor];  
  136.         NSArray *sortDes=[[NSArray alloc] initWithObjects:sort, nil nil];  
  137.         [request setSortDescriptors:sortDes];  
  138.         NSArray *getObject=[self.managedObjectContext  
  139.                             executeFetchRequest:request  
  140.                             error:error];  
  141.           
  142.         return [getObject objectAtIndex:0];  
  143.     }  
  144.     return nil;  
  145. }  
  146.   
  147. //从文件系统中删除sqlite文件  
  148. -(bool)deleteAllEntities{  
  149.     bool status=NO;  
  150.     NSError *error;  
  151.     @try{  
  152.         [[NSFileManager defaultManager] removeItemAtPath:[self storeURL].path  
  153.                                                    error:&error];  
  154.         status=YES;  
  155.     }  
  156.     @catch (NSException *exception) {  
  157.         status=NO;  
  158.     }  
  159.     @finally {  
  160.         return status;  
  161.     }  
  162. }  
  163.   
  164. @end  


3.后台执行程序

[objc] view plaincopyprint?在CODE上查看代码片派生到我的代码片
  1. - (void)loadBannerList:(void (^)(NSArray *bannerList, NSError *error))block {  
  2.       
  3.     NSParameterAssert(block);  
  4.       
  5.     [self POST:@"webresources/homePage"  
  6.             parameters:nil  
  7.             resultClass:BannerWrapper.class  
  8.             resultKeyPath:nil  
  9.             completion:^(AFHTTPRequestOperation *operation, id responseObject, NSError *error) {  
  10.           
  11.         //-----------------------Persistence DEMO---------------------  
  12.         //If network error, get data from CoreData, else save data into CoreData  
  13.         if (!error) {  
  14.             NSError *err;  
  15.             Persistence *persistence=[[Persistence alloc] init];  
  16.             BOOL save=[persistence saveMTLModel:responseObject error:&err];  
  17.             if (save==NO) {  
  18.                 NSLog(@"Save ERROR!");  
  19.             }  
  20.         }else{  
  21.             NSError *err;  
  22.             Persistence *persistence=[[Persistence alloc] init];  
  23.             BannerWrapper *resObject=[[BannerWrapper alloc] init];  
  24.             BannerWrapper *object=[[BannerWrapper alloc] init];  
  25.             object=[persistence getMTLmodel:resObject error:&err];  
  26.   
  27.             responseObject=object;  
  28.               
  29.             //这个地方异常的奇怪,从coredata中应该返回打Array类型变成了set类型,所以这里暂时作了一个转换。  
  30.             if ([object.bannerList isKindOfClass:[NSSet class]]) {  
  31.                 NSArray *objectArray = [(NSSet *)object.bannerList  allObjects];  
  32.                 ((BannerWrapper *)responseObject).bannerList=objectArray;  
  33.             }  
  34.         }  
  35.         //-----------------------------------------------------------  
  36.           
  37.         BannerWrapper *wrapper = responseObject;  
  38.         block(wrapper.bannerList, error);  
  39.           
  40.     }];  
  41. }