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创建数据持久化的过程。

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

Core Data with Mantle_第1张图片

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 文件

#import 

@interface BannerWrapper : MTLModel 

@property (nonatomic, readonly) bool result;
@property (copy, nonatomic, readonly) NSNumber *resultId;
@property (copy, nonatomic, readonly) NSString *resultMsg;
@property (copy, nonatomic) NSArray *bannerList;
+(NSSortDescriptor *)sortDescriptor;
@end

@interface Banner : MTLModel 

@property (copy, nonatomic, readonly) NSNumber *bannerId;
@property (copy, nonatomic, readonly) NSString *picUrl;
@property (copy, nonatomic, readonly) NSString *toDetailUrl;
@property (copy, nonatomic, readonly) NSNumber *width;
@property (copy, nonatomic, readonly) NSNumber *height;

@end


.m文件

#import "Banner.h"

@implementation BannerWrapper

#pragma mark - JSON serialization

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{
             @"result" : @"result",
             @"resultId" : @"resultId",
             @"resultMsg" : @"resultMSG",
             @"bannerList" : @"banner"
             };
}

+ (NSValueTransformer *)bannerListJSONTransformer
{
    return [NSValueTransformer mtl_JSONArrayTransformerWithModelClass:[Banner class]];
}

#pragma mark - Managed object serialization

+ (NSString *)managedObjectEntityName {
    return @"BannerWrapper";
}

+ (NSDictionary *)managedObjectKeysByPropertyKey {
    return nil;
}

+(NSDictionary *)relationshipModelClassesByPropertyKey{
    return @{
             @"bannerList"  : [Banner class],
             };
}

//在从coredata中取数据时的数据排序方式
+(NSSortDescriptor *)sortDescriptor{
    return [[NSSortDescriptor alloc] initWithKey:@"resultId" ascending:YES];
}

@end

@implementation Banner

#pragma mark - JSON serialization

+ (NSDictionary *)JSONKeyPathsByPropertyKey {
    return @{
             @"bannerId" : @"id",
             @"picUrl" : @"picUrl",
             @"toDetailUrl" : @"toDetailUrl",
             @"width":@"width",
             @"height":@"height"
             };
}

#pragma mark - Managed object serialization

+ (NSString *)managedObjectEntityName {
    return @"Banner";
}

+ (NSDictionary *)managedObjectKeysByPropertyKey {
    return nil;
}

@end


2.coredata 持久化类

Coredata主要元素简要介绍

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

Core Data with Mantle_第2张图片

  • 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文件

#import 

@interface Persistence : NSObject

//数据模型对象
@property(strong,nonatomic) NSManagedObjectModel *managedObjectModel;
//上下文对象
@property(strong,nonatomic) NSManagedObjectContext *managedObjectContext;
//持久性存储区
@property(strong,nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

//确定sqlite文件存储路径
-(NSURL *)storeURL;

//初始化Core Data使用的数据库
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator;

//managedObjectModel的初始化赋值函数
-(NSManagedObjectModel *)managedObjectModel;

//managedObjectContext的初始化赋值函数
-(NSManagedObjectContext *)managedObjectContext;

//保存MTLModel对象至coredata
-(BOOL)saveMTLModel:(MTLModel *)mtlModel
              error:(NSError * __autoreleasing *)error;

//从coredata中提取出MTLModel
-(MTLModel *)getMTLmodel:(MTLModel *)mtlModel
                   error:(NSError *__autoreleasing *)error;

//+ (NSFetchRequest *)fetchRequest;
@end




.m文件

#import "Persistence.h"

@implementation Persistence

@synthesize managedObjectContext;
@synthesize managedObjectModel;
@synthesize persistentStoreCoordinator;


//确定sqlite文件存储路径
-(NSURL *)storeURL{
    //得到数据库的路径
    //    NSString *docs = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
    //    //CoreData是建立在SQLite之上的,数据库名称需与Xcdatamodel文件同名
    //    NSURL *storeUrl = [NSURL fileURLWithPath:[docs stringByAppendingPathComponent:@"CoreData.sqlite"]];
    
    NSArray *documnetDir=NSSearchPathForDirectoriesInDomains(NSDocumentationDirectory, NSUserDomainMask, YES);
    NSString *docDir=[documnetDir objectAtIndex:0];
    NSString *path=[docDir stringByAppendingPathComponent:@"CoreData.sqlite"];
    NSURL *storeURL=[NSURL fileURLWithPath:path];
    return storeURL;
}


//初始化Core Data使用的数据库
-(NSManagedObjectModel *)managedObjectModel
{
    if (managedObjectModel != nil) {
        return managedObjectModel;
    }
    return [NSManagedObjectModel mergedModelFromBundles:nil];
}

//managedObjectModel的初始化赋值函数
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
    if (persistentStoreCoordinator != nil) {
        return persistentStoreCoordinator;
    }
    
    NSError *error = nil;
    persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc]
                                  initWithManagedObjectModel:self.managedObjectModel];
    if (![persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
                                                  configuration:nil
                                                            URL:[self storeURL]
                                                        options:nil
                                                          error:&error]) {
        NSLog(@"Error: %@,%@",error,[error userInfo]);
        [NSException raise:@"open failed" format:@"Reason:%@",[error localizedDescription]];
    }
    
    return persistentStoreCoordinator;
}

//managedObjectContext的初始化赋值函数
-(NSManagedObjectContext *)managedObjectContext
{
    if (managedObjectContext != nil) {
        return managedObjectContext;
    }
    
    NSPersistentStoreCoordinator *coordinator =self.persistentStoreCoordinator;
    
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc]init];
        [managedObjectContext setPersistentStoreCoordinator:coordinator];
    }
    
    return managedObjectContext;
}

//保存MTLModel对象至coredata
-(BOOL)saveMTLModel:(MTLModel *)mtlModel
              error:(NSError *__autoreleasing *)error{
    //-----Need Add Remove the Entity First  START---------
    NSManagedObject *exsitManagedObject=[self getManagedObject:mtlModel
                                                         error:error];
    if (exsitManagedObject!=nil) {
        [self.managedObjectContext deleteObject:exsitManagedObject];
        [self.managedObjectContext save:error];
    };
    //-----Need Add Remove the Entity First  END-----------
    
    NSManagedObject *managedObject = [MTLManagedObjectAdapter
                                      managedObjectFromModel:mtlModel
                                      insertingIntoContext:self.managedObjectContext
                                      error:error];
    
    if (managedObject==nil) {
        NSLog(@"[NSManagedObject] Error:%@",*error);
        return NO;
    }
    
    if (![self.managedObjectContext save:error]) {
        NSLog(@"[self.managedObjectContext] Error:%@",*error);
        return NO;
    };
    return YES;
};

//从coredata中提取出MTLModel
-(MTLModel *)getMTLmodel:(MTLModel *)mtlModel
                   error:(NSError *__autoreleasing *)error{
    
    NSManagedObject *managedObject=[self getManagedObject:mtlModel error:error];
    MTLModel *mrlMotel=[[MTLModel alloc] init];
    
    mrlMotel = [MTLManagedObjectAdapter modelOfClass:[mtlModel class]
                                   fromManagedObject:managedObject error:error];
    
    if (error) {
        NSLog(@"[mrlMotel] Error:%@",*error);
    }
    return mrlMotel;
};

//从coredata中获取已存的ManagedObject
-(NSManagedObject *)getManagedObject:(MTLModel *)mtlModel
                               error:(NSError *__autoreleasing *)error{
    NSString *entityName=[[mtlModel class] managedObjectEntityName];
    
    //获取entity中对象数量
    NSFetchRequest *requestCount=[NSFetchRequest fetchRequestWithEntityName:entityName];
    NSUInteger count=[self.managedObjectContext countForFetchRequest:requestCount
                                                               error:error];
    NSLog(@"count result:%d",count);
    NSLog(@"sortDescriptor result:%@",[[mtlModel class] sortDescriptor]);
    
    //获取entity中第一个对象.这个对象必须存在且唯一。
    if (count==1) {
        NSFetchRequest *request=[[NSFetchRequest alloc] init];
        [request setEntity:[NSEntityDescription entityForName:entityName
                                       inManagedObjectContext:self.managedObjectContext]];
        NSSortDescriptor *sort=[[mtlModel class] sortDescriptor];
        NSArray *sortDes=[[NSArray alloc] initWithObjects:sort, nil];
        [request setSortDescriptors:sortDes];
        NSArray *getObject=[self.managedObjectContext
                            executeFetchRequest:request
                            error:error];
        
        return [getObject objectAtIndex:0];
    }
    return nil;
}

//从文件系统中删除sqlite文件
-(bool)deleteAllEntities{
    bool status=NO;
    NSError *error;
    @try{
        [[NSFileManager defaultManager] removeItemAtPath:[self storeURL].path
                                                   error:&error];
        status=YES;
    }
    @catch (NSException *exception) {
        status=NO;
    }
    @finally {
        return status;
    }
}

@end


3.后台执行程序

- (void)loadBannerList:(void (^)(NSArray *bannerList, NSError *error))block {
    
    NSParameterAssert(block);
    
    [self POST:@"webresources/homePage"
            parameters:nil
            resultClass:BannerWrapper.class
            resultKeyPath:nil
            completion:^(AFHTTPRequestOperation *operation, id responseObject, NSError *error) {
        
        //-----------------------Persistence DEMO---------------------
        //If network error, get data from CoreData, else save data into CoreData
        if (!error) {
            NSError *err;
            Persistence *persistence=[[Persistence alloc] init];
            BOOL save=[persistence saveMTLModel:responseObject error:&err];
            if (save==NO) {
                NSLog(@"Save ERROR!");
            }
        }else{
            NSError *err;
            Persistence *persistence=[[Persistence alloc] init];
            BannerWrapper *resObject=[[BannerWrapper alloc] init];
            BannerWrapper *object=[[BannerWrapper alloc] init];
            object=[persistence getMTLmodel:resObject error:&err];

            responseObject=object;
            
            //这个地方异常的奇怪,从coredata中应该返回打Array类型变成了set类型,所以这里暂时作了一个转换。
            if ([object.bannerList isKindOfClass:[NSSet class]]) {
                NSArray *objectArray = [(NSSet *)object.bannerList  allObjects];
                ((BannerWrapper *)responseObject).bannerList=objectArray;
            }
        }
        //-----------------------------------------------------------
        
        BannerWrapper *wrapper = responseObject;
        block(wrapper.bannerList, error);
        
    }];
}


你可能感兴趣的:(IOS)