Quantcast
Channel: CSDN博客移动开发推荐文章
Viewing all articles
Browse latest Browse all 5930

iOS项目拆分:数据本地持久化(4)

$
0
0

Core Data是有苹果官方提供的框架(#import <CoreData/CoreData.h>),实现数据持久化存储。Core Data实际上是将数据库的创建、表的创建、对象和表的转换等操作封装起来,极大的简化了操作。使用Core Data进⾏数据库存取不需要手动创建数据库,创建数据库的过程完全由Core Data框架自动完成,使用者需要做的就是把模型创建起来。

Core Date与SQLite相比较,SQLite比较原始,操作比较复杂,使用的是C的函数对数据库进行操作,但是SQLite可控性更强,并且能够跨平台。
  

以下是Core Data操作中经常使用的几个类:

1、NSManagedObjectModel:被管理的对象模型,相当于实体,不过它包含 了实体间的关系。
2、NSManagedObjectContext:被管理的对象上下文,相当于操作实际内容 作用:插入数据 查询 更新 删除
3、NSPersistentStoreCoordinator:持久化存储助理,用于数据库的连接器。
4、NSFetchRequest :获取数据的请求,用于数据查询,相当于查询语句。
5、NSPredicate:相当于查询条件。
6、NSEntityDescription:实体结构。
下面,讲解Core Data的简单使用

在创建项目的时候可以选择使用Core Data,项目创建成功后,在AppDelegate类中系统会自动添加相关代码,此外,还会自动生成一个数据模型文件 工程名.xcdatamodeld

这里写图片描述

AppDelegate.h类中对应生成的代码

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>//系统自动引入类
@interface AppDelegate : UIResponder <UIApplicationDelegate> 
@property (strong, nonatomic) UIWindow *window;
@property (readonly, strong) NSPersistentContainer *persistentContainer;
- (void)saveContext;
@end

AppDelegate.m类中对应生成的代码,此处注意在XCode中自动生成的代码较之前有所变动

#pragma mark - Core Data stack

@synthesize persistentContainer = _persistentContainer;

- (NSPersistentContainer *)persistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {
        if (_persistentContainer == nil) {
            _persistentContainer = [[NSPersistentContainer alloc] initWithName:@"Test123"];
            [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
                if (error != nil) {
                    // 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.

                    /*
                     Typical reasons for an error here include:
                     * The parent directory does not exist, cannot be created, or disallows writing.
                     * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                     * The device is out of space.
                     * The store could not be migrated to the current model version.
                     Check the error message to determine what the actual problem was.
                    */
                    NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                    abort();
                }
            }];
        }
    }

    return _persistentContainer;
}

#pragma mark - Core Data Saving support

- (void)saveContext {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSError *error = nil;
    if ([context hasChanges] && ![context 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();
    }
}

如果在创建项目的时候没有勾选Use Core Data选项,但是在后面需要使用,需要手动添加一个Data Model文件和手动的添加AppDelegate中的相关代码

这里写图片描述

注:创建Data Model文件时需要注意,文件名称要与AppDelegate.m中managedObjectModel方法中提到的文件名称相匹配,ios8的Xcode排版发生了一些变动,需要注意

在生成Data Model文件后,在~~.xcdatamodeld里面添加实体和关系添加实体如图所示:

这里写图片描述
这里写图片描述
注:这里实际上就是向数据库中添加表格和建立表格之间的关联

完成以上步骤,数据库中表格的创建就已经完成,和使用SQLite比较,省略了sql语句以及调用C函数操作数据库的步骤,另外,在创建实体的时候不需要设置主键,实体对象的属性的类型是OC的类型,实体中其他实体对象类型是通过建立关系添加的。

创建好实体后,可以通过添加NSManagedObject subclass文件(注:创建模型对象的类, “Editor > Create NSManagedobject Subclass”。),系统可以自动添加实体对应的数据模型类,如图所示:
这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

这里写图片描述

以下是封装好的CoreDataManaer单例文件

#import <Foundation/Foundation.h>
@interface CoreDataManager : NSObject
/**
 *  单例的初始化类方法
 *  @return CoreDataManager
 */
+ (CoreDataManager *)defaultManager;
/**
 *  添加一个对象模型到数据库中
 *  @param name       模型类的名字
 *  @param dictionary 需要对应赋值的属性
 */
- (void)addManagedObjectModelWithName:(NSString *)name dictionary:(NSDictionary *)dictionary;
/**
 *  查询对象模型
 *  @param name      模型类的名字
 *  @param predicate 创建一个谓词
 *  @param sortkeys  用来排序的Keys(注意是个数组)
 *  @return 返回查到的对象, 在外部使用时应与name对应
 */
- (NSArray *)fetchManagedObjectModelWithName:(NSString *)name predicate:(NSPredicate *)predicate sortKeys:(NSArray *)sortkeys;
/**
 *  删除对象模型
 *  @param models 对象模型数组(注意是数组, 尽管是删除一个也要数组)
 */
- (void)deleteAllManagedObjectModels:(NSArray *)models;
@end
#import "CoreDataManager.h"
#import <CoreData/CoreData.h>
@interface CoreDataManager ()
@property (nonatomic, strong) NSManagedObjectContext * managedObjectContext;
@property (nonatomic, strong) NSManagedObjectModel * managedObjectModel;
@property (nonatomic, strong) NSPersistentStoreCoordinator * persistentStoreCoordinator;
@end
@implementation CoreDataManager
static CoreDataManager * s_defaultManager = nil;
+ (CoreDataManager *)defaultManager {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        s_defaultManager = [[CoreDataManager alloc] init];
    });
    return s_defaultManager;
}
/**
 *  单例的初始化方法, 在init方法中初始化单例类持有的对象
 *  @return 初始化后的对象
 */
- (instancetype)init
{
    self = [super init];
    if (self) {
        // 添加观察者, 当ManagerObjectContext发生变化时调用saveContext方法
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(saveContext) name:NSManagedObjectContextObjectsDidChangeNotification object:nil];
    }
    return self;
}
- (void)addManagedObjectModelWithName:(NSString *)name dictionary:(NSDictionary *)dictionary  {
    NSManagedObject * managerObject = [NSEntityDescription insertNewObjectForEntityForName:name inManagedObjectContext:self.managedObjectContext];
    [managerObject setValuesForKeysWithDictionary:dictionary];
}
- (NSArray *)fetchManagedObjectModelWithName:(NSString *)name predicate:(NSPredicate *)predicate sortKeys:(NSArray *)sortkeys {
    // 实例化查询请求
    NSFetchRequest * fetchRequest = [NSFetchRequest fetchRequestWithEntityName:name];
    // 谓词搜索如果没有谓词, 那么默认查询全部
    if (predicate) {
        [fetchRequest setPredicate:predicate];
    }
    // 如果没有用来排序的key, 那么默认不排序
    if (sortkeys) {
        // 如果有排序的Key就先创建一个数组来接收多个NSSortDescriptor对象(尽管是一个, 因为setSortDescriptors:方法需要数组作为参数)
        NSMutableArray * sortDescriptorKeys = [NSMutableArray new];
        // 遍历所有的用来排序的key
        for (NSString * key in sortkeys) {
            // 每有一个Key, 就使用该key来创建一个NSSortDescriptor
            NSSortDescriptor * sortDescriptor = [[NSSortDescriptor alloc] initWithKey:key ascending:YES];
            // 在sortDescriptorKeys数组中添加一个NSSortDescriptor元素
            [sortDescriptorKeys addObject:sortDescriptor];
        }
        // 查询请求设置排序方式
        [fetchRequest setSortDescriptors:sortDescriptorKeys];
    }
    // 使用数组来接收查询到的内容
    NSArray * fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
    // 如果数组为nil
    if (fetchedObjects == nil) {
        // 创建一个新的数组返回, 在外部去做判断
        fetchedObjects = [NSArray new];
    }
    // 返回查找到的数组
    return fetchedObjects;
}
- (void)deleteAllManagedObjectModels:(NSArray *)models {
    // 遍历删除传进来数组中的元素对应的表内容
    for (NSManagedObject * object in models) {
        // 使用管理者删除对象, 数组中的元素并没有缺少
        [self.managedObjectContext deleteObject:object];
    }
}
#pragma mark - Core Data stack
- (NSURL *)applicationDocumentsDirectory {
    NSLog(@"%@", [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]);
    return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
/**
 *  模型器的懒加载方法
 *  @return 唯一的模型器
 */
- (NSManagedObjectModel *)managedObjectModel {

    if (!_managedObjectModel) {

        NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"PalmEfamily" withExtension:@"momd"];
        _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
    }
    return _managedObjectModel;
}
/**
 *  链接器的懒加载方法
 *  @return 唯一的链接器对象
 */
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    if (!_persistentStoreCoordinator) {

        _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
        NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"PalmEfamily.sqlite"];
//        [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:nil];

        [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:@{NSInferMappingModelAutomaticallyOption : @YES, NSMigratePersistentStoresAutomaticallyOption : @YES } error:nil];
    }
    return _persistentStoreCoordinator;
}
/**
 *  管理者的懒加载方法
 *  @return 唯一的管理者对象
 */
- (NSManagedObjectContext *)managedObjectContext {
    if (!_managedObjectContext) {
        _managedObjectContext = [[NSManagedObjectContext alloc] init];
        [_managedObjectContext setPersistentStoreCoordinator:[self persistentStoreCoordinator]];
    }
    return _managedObjectContext;
}
/**
 *  ManagerObjectContext的保存方法
 */
- (void)saveContext {
    [self.managedObjectContext save:nil];
}
@end

以上是针对使用Core Data的一些总结,如存在问题请提出评论。

作者:Cituses 发表于2016/9/21 10:38:39 原文链接
阅读:264 评论:0 查看评论

Viewing all articles
Browse latest Browse all 5930

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>