08、CoreData的简单应用
一、CoreData数据库框架的优势
1、CoreData历史
CoreData数据持久化框架是Cocoa API的一部分,他允许按照实体-属性-值模型组织数据,并以XML、二进制文件或者SQLite数据文件的格式持久化数据,主要提供对象-关系映射(ORM)功能,把OC对象转换为数据保存在文件中,也可以将数据转换为OC对象。
2、sqlite与CoreData的区别
sqlite:
- 基于C接口,需要使用sql语句,代码繁琐
- 在处理大量数据时,表关系更在直接
- 在OC中不是可视化的
CoreData: - 可视化,有undo/redo能力
- 可以实现多种文件格式NSSQLiteStoreType、NSBinaryStoreType、NSInMemoryStoreType、NSXMLStoreType
-
苹果官方API支持,与iOS结合更紧密
3、CoreData核心对象
实体管理类:NSManagedObject
实体描述类:NSEntityDescription
数据管理器类:NSManagedObjectContext
数据连接器类:NSPersistentStoreCoordinator
数据模型器类:NSManagedObjectModel
CoreData.png
CoreData的存储过程:
被管理对象的上下文(NSManagedObjectContext)将被管理的对象(NSManagedObject)交给持久化数据助理(NSPersistentStoreCoordinator),持久化数据助力将被管理对象转换为数据文件(XML,SQLite,Binary)存储到文件系统中(FileSystem)
读取过程:
助理从文件系统中读取出数据文件,将数据文件转换为被管理的对象交给context操作
二、CoreData的使用
1、创建工程
一定要勾选下面的Use Core Data
Core_Data.png
2、进入工程就可以看见多了一个文件
点击下方的Add Entity➕就可以添加实体类
使用Attributes选项下的+ -号可以给表添加和删除字段
在Relationships下面可以添加表之间的关系
3、建一个实体类
选择Core Data 下的NSManagedObject subclass文件新建,一直点next,选择要新建的model,选择新建类的实体。
Use scalar properties for primitive data types选项,如果勾选,数据库中的integer类型就在类中变成int,不勾选,就变成NSNumber
![屏幕快照 2017-01-20 上午10.09.06.png](https://img.haomeiwen.com/i2758407/b62255ff114bbfe0.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
4、这时就会产生四个类
屏幕快照 2017-01-20 上午10.10.39.png
这时我们就可以对学生这张表进行增删改查的操作了
@implementation ViewController
//该方法是用来获取AppDelegate对象
-(AppDelegate*)appDalegate{
return (AppDelegate*)[UIApplication sharedApplication].delegate;
}
//获取上下文,对数据对象进行操作
-(NSManagedObjectContext*)managedObjectContext{
return [self appDalegate].managedObjectContext;
}
//增加数据
-(void)addData{
//创建需要增加的数据对象
//第一个参数:实体名称,表名
//第二个参数:该数据被哪个context操作
Student* stu_1=[NSEntityDescription insertNewObjectForEntityForName:@"Student" inManagedObjectContext:[self managedObjectContext]];
stu_1.name = @"余菲";
stu_1.age = @18;
//将增加操作同步到底层
[[self appDalegate] saveContext];
}
//读取
-(void)queryData{
//创建要被读取的实体对象
//第一个参数:实体类的名称
//第二个参数:所在的上下文
NSEntityDescription* studentEntity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:[self managedObjectContext]];
//创建查询请求对象
NSFetchRequest* fetch=[[NSFetchRequest alloc] init];
//设置该请求要查询的实体对象
[fetch setEntity:studentEntity];
//开始查询
//返回值为数组,数组中的元素就是该实体类对应的的类型对象
NSArray* array=[[self managedObjectContext] executeFetchRequest:fetch error:nil];
//遍历数组,取出对象
for (Student* student in array) {
NSLog(@"name=%@,age=%@",student.name,student.age);
}
}
//更新操作
-(void)updateData{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch
//谓词,查询条件 相当于sql语句中的where
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@", @"余菲"];
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
//按照哪个属性进行排序
//key:排序条件的属性名
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
// if (fetchedObjects == nil) {
//
// }
if (fetchedObjects.count) {
//更新操作
for (Student* student in fetchedObjects) {
student.age=@20;
}
}
//对CoreData存储的内容进行了修改,必须进行同步操作
[[self appDalegate] saveContext];
}
//删除操作
-(void)removeData{
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSEntityDescription *entity = [NSEntityDescription entityForName:@"Student" inManagedObjectContext:[self managedObjectContext]];
[fetchRequest setEntity:entity];
// Specify criteria for filtering which objects to fetch
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = %@ && age = %@", @"余菲",@18];
[fetchRequest setPredicate:predicate];
// Specify how the fetched objects should be sorted
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
ascending:YES];
[fetchRequest setSortDescriptors:[NSArray arrayWithObjects:sortDescriptor, nil]];
NSError *error = nil;
NSArray *fetchedObjects = [[self managedObjectContext] executeFetchRequest:fetchRequest error:&error];
if (fetchedObjects != nil) {
for (Student* student in fetchedObjects) {
//删除操作
[[self managedObjectContext] deleteObject:student];
}
}else{
NSLog(@"未找到");
}
[[self appDalegate] saveContext];
}
//非底层的数据对象的所有操作都是通过上下文完成的
- (void)viewDidLoad {
[super viewDidLoad];
// [self addData];//增加数据
// [self updateData];
[self queryData];
[self removeData];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
在这里,大家可以简单的使用CoreData进行一个学生列表的管理
1.建一个TableView
#import "StudentVC.h"
#import "Android.h"
#import "AppDelegate.h"
@interface StudentVC ()<UITableViewDataSource,UITableViewDelegate>
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property(nonatomic,strong)NSMutableArray* allDataMArray;//存放所有数据
@end
@implementation StudentVC
//_allDataMArray的懒加载
-(NSMutableArray*)allDataMArray{
if (!_allDataMArray) {
_allDataMArray=[[NSMutableArray alloc] init];
}
return _allDataMArray;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.automaticallyAdjustsScrollViewInsets=NO;
[self insertData];//插入操作
[self queryData];//查询操作
}
//返回行数
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.allDataMArray.count;
}
//定义单元格
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell* cell=[tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];
Android* android=self.allDataMArray[indexPath.row];
cell.textLabel.text=android.name;
cell.detailTextLabel.text=android.sex;
cell.imageView.image=[UIImage imageWithData:android.headImg];
return cell;
}
//获取appDelegate
-(AppDelegate*)appDelegate{
return (AppDelegate*)[UIApplication sharedApplication].delegate;
}
//获取managedContext
-(NSManagedObjectContext*)managedContext{
return [self appDelegate].managedObjectContext;
}
//首次运行应用程序的时候,插入全班同学的数据·,再次打开时,就不进行插入操作了
-(void)insertData{
//首次启动的时候,由于我们没有存储值,所以获取到的值为NO。当我们启动之后就将该值置为YES,
//isFirst==NO 说明首次启动 若等于YES 就不是首次启动
BOOL isFirst=[[NSUserDefaults standardUserDefaults] boolForKey:@"isFirst"];
if (isFirst) {
return;
}
//不进if分支,说明是首次启动
NSDictionary* dic_1=@{@"name":@"王翰",@"sex":@"男"};
NSDictionary* dic_2=@{@"name":@"李博",@"sex":@"男"};
NSDictionary* dic_3=@{@"name":@"雷龙飞",@"sex":@"男"};
NSDictionary* dic_4=@{@"name":@"樊李鹏",@"sex":@"男"};
NSDictionary* dic_5=@{@"name":@"张泽安",@"sex":@"男"};
NSDictionary* dic_6=@{@"name":@"刘元",@"sex":@"男"};
NSDictionary* dic_7=@{@"name":@"李豫君",@"sex":@"男"};
NSDictionary* dic_8=@{@"name":@"李雄飞",@"sex":@"男"};
NSDictionary* dic_9=@{@"name":@"任涛",@"sex":@"男"};
NSDictionary* dic_10=@{@"name":@"薛佳伟",@"sex":@"男"};
NSDictionary* dic_11=@{@"name":@"余菲",@"sex":@"女"};
NSArray* array=@[dic_1,dic_2,dic_3,dic_4,dic_5,dic_6,dic_7,dic_8,dic_9,dic_10,dic_11];
for (NSDictionary* item in array) {
Android* android=[NSEntityDescription insertNewObjectForEntityForName:@"Android" inManagedObjectContext:[self managedContext]];
android.name=item[@"name"];
android.sex=item[@"sex"];
UIImage* headImg=[UIImage imageNamed:@"10.JPG"];
android.headImg=UIImagePNGRepresentation(headImg);
}
//进行同步操作
[[self appDelegate] saveContext];
//将isFirst置为YES下次就不会增加数据了
[[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"isFirst"];
}
//查询操作
-(void)queryData{
//需要被查询的实体对象,它是通过实体描述类来获取的
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Android" inManagedObjectContext:[self managedContext]];
//需要查询请求对象
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
//为查询请求对象设置实体对象
[fetchRequest setEntity:entity];
//通过上下文发起获取数据的请求,返回值为数组类型
NSArray* array=[[self managedContext] executeFetchRequest:fetchRequest error:nil];
if (array&&array.count) {
[self.allDataMArray addObjectsFromArray:array];
}
}
//返回行高
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
return 100;
}
//删除操作
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
//先删除数据,再删除单元格,因为删除单元格的时候会执行代理方法,会执行代理方法;如果我们先删除单元格,执行代理方法的时候,数据和单元格的个数就不匹配了,就有可能崩溃
if (editingStyle==UITableViewCellEditingStyleDelete) {
//当我们对数据做了持久化之后,先删除数据库或者coreData中的数据,再删除本地集合中的数据
Android* android=[self.allDataMArray objectAtIndex:indexPath.row];
//删除coreData中的数据
[[self managedContext] deleteObject:android];
//同步操作
[[self appDelegate] saveContext];
//删除了可变数组中的数据
[self.allDataMArray removeObjectAtIndex:indexPath.row];
//删除单元格,执行tableView的代理方法
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:(UITableViewRowAnimationLeft)];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/*
#pragma mark - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
@end
运行结果如下:
屏幕快照 2017-01-20 上午10.14.56.png ![屏幕快照 2017-01-20 上午10.15.23.png](https://img.haomeiwen.com/i2758407/9556cd20009016dd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
今天的内容就完啦😝😝😝