今天聊聊CoreData的使用,通过懒加载的方式来创建,和数据库中数据的抓取,fetchedResultController的代理,一些简单的使用。
coredata用于做数据持久化,适合大数据量的存储和查询
coredata虽然不是数据库,但是可以使用数据库,xml等方式来存储数据,看看coredata的用法吧!
1.创建一个coredatamodel
2.创建一个实体
3.添加属性
4.创建model
好了这些实体,model也创建完了,开始来操作这些东西了。
第一步:
创建一个管理类:用到了懒加载的方式。创建了一个sqlite的数据库。
.h
//
// CoreDataManager.h
// CoreData-demo
//
// Created by mac on 16/8/19.
// Copyright © 2016年 mac. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@interface CoreDataManager : NSObject
//创建单例
+(instancetype)shareManager;
//定义三个必要的属性,这里使用懒加载
//mo上下文
@property(nonatomic,strong,readonly)NSManagedObjectContext *managedObjectContext;
//mo模型
@property(nonatomic,strong,readonly)NSManagedObjectModel *managedObjectModel;
//协调器
@property(nonatomic,strong,readonly)NSPersistentStoreCoordinator *persistentStoreCoordinator;
//保存上下文方法
-(void)saveContext;
/*
对数据的
增加 -add
删 -delete
改 -updata
查 -fentch
*/
//自定义一个方法,其中的操作就是通过实体名插入你想要的数据
-(NSManagedObject *)addManagerObjectWithEntityname:(NSString *)entity;
//查询方法,需要谓词,排序方式
-(NSArray *)fentchEntityName:(NSString *)entityName predicate:(NSPredicate *)predicate orderby:(NSArray *)sortDescriptors;
.m实现
//
// CoreDataManager.m
// CoreData-demo
//
// Created by mac on 16/8/19.
// Copyright © 2016年 mac. All rights reserved.
//
#import "CoreDataManager.h"
//定义一个单例对象
static CoreDataManager *instance = nil;
@implementation CoreDataManager
//单例方法实现
+(instancetype)shareManager{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[CoreDataManager alloc] init];
});
return instance;
}
//等效属性--因为只有get方法
@synthesize managedObjectModel = _managedObjectModel;
@synthesize managedObjectContext = _managedObjectContext;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
//1.模型文件对象
-(NSManagedObjectModel *)managedObjectModel{
//懒加载
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
//获取到自己创建的coredatamodel文件的路径
NSURL *modelUrl = [[NSBundle mainBundle]URLForResource:@"CoreDataModel" withExtension:@"momd"];//后缀名
_managedObjectModel = [[NSManagedObjectModel alloc]initWithContentsOfURL:modelUrl];
return _managedObjectModel;
}
//2.创建协调器
-(NSPersistentStoreCoordinator *)persistentStoreCoordinator{
if (_persistentStoreCoordinator !=nil) {
return _persistentStoreCoordinator;
}
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:self.managedObjectModel];//PS:这里需要点语法
//数据库的存储路径
NSURL *storeUrl = [NSURL fileURLWithPath:[NSHomeDirectory() stringByAppendingString:@"/Documents/Database.sqlite"]];
NSError *error = nil;
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
//给协调器添加一个可持久化的对象
NSPersistentStore *persistentStore = [_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType
configuration:nil
URL:storeUrl
options:nil
error:&error];
if (!persistentStore) {
//有错误
// Report any error we got.
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
dict[NSUnderlyingErrorKey] = error;
error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict];
// Replace this 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()会是app退出,然后生成一个崩溃日志
//在开发阶段使用ok,但是发布的时候要注释掉.
abort();
}
return _persistentStoreCoordinator;
}
//3.上下文
-(NSManagedObjectContext *) managedObjectContext{
if (_managedObjectContext !=nil) {
return _managedObjectContext;
}
//拷贝一份协调器
NSPersistentStoreCoordinator *psc = [self persistentStoreCoordinator];
//判断是否为空
if (!psc) {
return nil;
}
//创建对象,并设置操作类型,在主队列
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
//协调器
_managedObjectContext.persistentStoreCoordinator = psc;
return _managedObjectContext;
}
//方法实现,当存储数据需要改变时调用 --增加,删除,更新操作
-(void)saveContext{
NSManagedObjectContext *context = self.managedObjectContext;
if (context != nil) {
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
//如果context发生变化,会发生crash
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
//如果context没有发生变化,不会进入...
}
}
还需要在.m中实现插入和查询方法,但是我们在使用fetchedResultContoller的时候无需用到查询方法
//添加
-(NSManagedObject *)addManagerObjectWithEntityname:(NSString *)entity{
//插入
NSManagedObject *manageObject = [NSEntityDescription insertNewObjectForEntityForName:entity inManagedObjectContext:self.managedObjectContext];
//返回一个MO对象,进行自定义操作
return manageObject;
}
-(NSArray*)fentchEntityName:(NSString *)entityName predicate:(NSPredicate *)predicate orderby:(NSArray *)sortDescriptors{
//抓取请求
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//实体对象
NSEntityDescription *entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch
//使用自己定义谓词
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
//使用自己定义的排序操作
[fetchRequest setSortDescriptors:sortDescriptors];
NSError *error = nil;
NSArray *fetchedObjects = [self.managedObjectContext executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects == nil) {
NSLog(@"error");
}
//返回查询到的数组
return fetchedObjects;
}
实战演练:通过在tableview的来调用数据库中的内容,做到添加内容的效果。
两个界面:一个tableview 一个添加内容的界面
tableview界面:这里只是实现了添加内容进入数据库的效果,通过fetchedResultController的抓取来实现的。
#import "ViewController.h"
#import "CoreDataManager.h"
#import "Hunter.h"
@interface ViewController ()<UITableViewDataSource,UITableViewDelegate,NSFetchedResultsControllerDelegate>{
//抓取结果控制器--返回的结果都在这里面
NSFetchedResultsController *fetchedResults;
}
@property (weak, nonatomic) IBOutlet UITableView *myTableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(@"%@",NSHomeDirectory());
self.myTableView.delegate = self;
self.myTableView.dataSource = self;
[self loadData];
}
-(void)loadData{
CoreDataManager *manager = [CoreDataManager shareManager];
//抓取请求
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] initWithEntityName:@"Hunter"];//实体名
//可以选择写
fetchRequest.predicate = nil;
//必写
NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
fetchRequest.sortDescriptors = @[sort];
//作用:抓取最终的结果
//(1)抓取结果
fetchedResults = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:manager.managedObjectContext
sectionNameKeyPath:nil
cacheName:nil];
//调用代理
fetchedResults.delegate = self;
//(2)执行查询的数据
NSError *error = nil;
//这时候fetchResults中就有结果了
[fetchedResults performFetch:&error];
}
#pragma mark -dataSource , delegate
//组数
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
return fetchedResults.sections.count;
}
//行数
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [[fetchedResults.sections objectAtIndex:section]numberOfObjects];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cellID"];
if (cell ==nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cellID"];
}
//取出对象
Hunter *model = [fetchedResults objectAtIndexPath:indexPath];
//输出两个值
cell.textLabel.text = model.name;
//model.age是nsnumber类型
cell.detailTextLabel.text = [NSString stringWithFormat:@"%d", model.age];
return cell;
}
#pragma mark - fetchedResultsController 代理
/*
controller:NSFetchedResultsController对象
ChangeObject:修改的对象
indexPath: 对象在数据库中的位置
ChangeType:修改的类型
*/
//监听数据库中的变化
-(void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{
if (type == NSFetchedResultsChangeInsert) {
//刷新tableview
[self.myTableView reloadData];
}
}
@end
添加内容界面,只需要把内容添加的数据库即可
//
// AddDataViewController.m
// CoreData-demo
//
// Created by mac on 16/8/19.
// Copyright © 2016年 mac. All rights reserved.
//
#import "AddDataViewController.h"
#import "CoreDataManager.h"
#import "Hunter.h"
@interface AddDataViewController ()
@property (weak, nonatomic) IBOutlet UITextField *nameText;
@property (weak, nonatomic) IBOutlet UITextField *ageText;
@property (weak, nonatomic) IBOutlet UITextField *heightText;
@property (weak, nonatomic) IBOutlet UITextField *workText;
@end
@implementation AddDataViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)buttonAction:(UIButton *)sender {
CoreDataManager *manager = [CoreDataManager shareManager];
Hunter *model = (Hunter *)[manager addManagerObjectWithEntityname:@"Hunter"];
model.name = self.nameText.text;
model.age = [self.ageText.text intValue];
model.height = [self.heightText.text floatValue];
model.work = self.workText.text;
//保存
[manager saveContext];
[self.navigationController popViewControllerAnimated:YES];
}
@end