接 coredata基本用法(一)
以一个小项目为例:
项目结构如图:
appdelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.window.rootViewController = [[UINavigationController alloc] initWithRootViewController:[[ViewController alloc] init]];
return YES;
}ViewController.m
//
// ViewController.m
// 06-coredata
//
#import "ViewController.h"
#import "Person.h"
#import "Dog.h"
#import "AddPersonViewController.h"
#import "DogViewController.h"
@interface ViewController () <UITableViewDataSource, UITableViewDelegate, NSFetchedResultsControllerDelegate>
{
UITableView * _tableView;
NSManagedObjectContext * _managedObjectContext;
NSFetchedResultsController * _fetchedResultsController;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor whiteColor];
self.title = @"主人";
[self connectDataBase];
//排序
NSFetchRequest * request = [[NSFetchRequest alloc] initWithEntityName:@"Person"];
NSSortDescriptor * sortDes = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:NO];
request.sortDescriptors = @[sortDes];
//可以实时监测数据库发生的变化 request是实体Person的,所以下面的fetch是查询Person实体
_fetchedResultsController = [[NSFetchedResultsController alloc]initWithFetchRequest:request managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
_fetchedResultsController.delegate = self;
[_fetchedResultsController performFetch:nil];//触发查询
[self initTableView];
}
- (void) initTableView {
_tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addPerson)];
}
- (void) addPerson {
AddPersonViewController * newPerson = [[AddPersonViewController alloc] init];
[self.navigationController pushViewController:newPerson animated:YES];
[newPerson setRetDict:^(NSDictionary * dict) {
Person * p = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:_managedObjectContext];
p.name = dict[@"name"];
p.age = [NSNumber numberWithInt:[dict[@"age"] intValue]];
p.sex = dict[@"sex"];
[_managedObjectContext save:nil];
}];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cellid = @"cellid";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellid];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellid];
}
cell.textLabel.text = [_fetchedResultsController.fetchedObjects[indexPath.row] name];
NSString * ageStr = [NSString stringWithFormat:@"%i", [[_fetchedResultsController.fetchedObjects[indexPath.row] age] intValue]];
cell.detailTextLabel.text = [NSString stringWithFormat:@"age:%@,sex:%@", ageStr, [_fetchedResultsController.fetchedObjects[indexPath.row] sex]];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _fetchedResultsController.fetchedObjects.count;
}
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
DogViewController *vc = [[DogViewController alloc]init];
//fetchedObjects查询所有person
vc.person = _fetchedResultsController.fetchedObjects[indexPath.row];
//_managedObjectContext 就是和数据库的连接,传过去后可以直接操作数据库了
vc.context = _managedObjectContext;
[self.navigationController pushViewController:vc animated:YES];
}
#pragma mark NSFetchedResultsControllerDelegate
//实时监测数据变化
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
switch (type) {
case NSFetchedResultsChangeInsert:
{
//有数据插入时 更新UI
[_tableView insertRowsAtIndexPaths:@[newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
}
break;
case NSFetchedResultsChangeDelete:
{
//删除时变化监测
}
break;
case NSFetchedResultsChangeUpdate:
{
//数据更新时
}
break;
default:
break;
}
}
#pragma connect database
- (void) connectDataBase {
//是把所有的CoreData里面创建的数据模型进行整合
NSManagedObjectModel * model = [NSManagedObjectModel mergedModelFromBundles:nil];
NSPersistentStoreCoordinator * coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
NSString * path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/personCoredata.db"];
NSError * error = nil;
//创建数据库
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:path] options:nil error:&error];
if (error) {
NSLog(@"error message : %@", error);
}
else
{
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_managedObjectContext.persistentStoreCoordinator = coordinator;//字面意思就是 持久化存储协调器
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
AddPersonViewController.h
#import <UIKit/UIKit.h> @interface AddPersonViewController : UIViewController @property(nonatomic, copy) void(^retDict)(NSDictionary * dict); //这个完全是为了把值传回ViewController @end
AddPersonViewController.m
//
// AddPersonViewController.m
#import "AddPersonViewController.h"
@interface AddPersonViewController ()
{
UITextField * _nameTextField;
UITextField * _ageTextField;
UITextField * _sexTextField;
}
@end
@implementation AddPersonViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = [UIColor whiteColor];
//这里面的东西没什么好说的
UILabel * nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100, 70, 30)];
nameLabel.textAlignment = NSTextAlignmentCenter;
nameLabel.text = @"姓名:";
[self.view addSubview:nameLabel];
_nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(130, 100, 200, 30)];
_nameTextField.placeholder = @"请输入姓名";
[self.view addSubview:_nameTextField];
UILabel * ageLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100 + 50, 70, 30)];
ageLabel.textAlignment = NSTextAlignmentCenter;
ageLabel.text = @"年龄:";
[self.view addSubview:ageLabel];
_ageTextField = [[UITextField alloc] initWithFrame:CGRectMake(130, 100 + 50, 200, 30)];
_ageTextField.placeholder = @"请输入年龄";
[self.view addSubview:_ageTextField];
UILabel * sexLabel = [[UILabel alloc] initWithFrame:CGRectMake(50, 100 + 100, 70, 30)];
sexLabel.textAlignment = NSTextAlignmentCenter;
sexLabel.text = @"性别:";
[self.view addSubview:sexLabel];
_sexTextField = [[UITextField alloc] initWithFrame:CGRectMake(130, 100 + 100, 200, 30)];
_sexTextField.placeholder = @"请输入性别";
[self.view addSubview:_sexTextField];
UIButton * btn = [[UIButton alloc] initWithFrame:CGRectMake(50, 100 + 150, 70, 30)];
[btn setTitle:@"确定" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
btn.backgroundColor = [UIColor blueColor];
[btn addTarget:self action:@selector(btnClick) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void) btnClick {
if (_nameTextField.text == nil || _nameTextField.text.length < 1) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示信息" message:@"名字不能为空" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
NSLog(@"no name");
}else if (_ageTextField.text == nil || _ageTextField.text.length < 1) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示信息" message:@"年龄不能为空" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
NSLog(@"no age");
}else if (_sexTextField.text == nil || _sexTextField.text.length < 1) {
UIAlertController * alertController = [UIAlertController alertControllerWithTitle:@"提示信息" message:@"性别不能为空" preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
UIAlertAction * okAction = [UIAlertAction actionWithTitle:@"好的" style:UIAlertActionStyleDefault handler:nil];
[alertController addAction:cancelAction];
[alertController addAction:okAction];
[self presentViewController:alertController animated:YES completion:nil];
NSLog(@"no sex");
}else {
NSLog(@"all have");
NSDictionary * dict = @{@"name" : _nameTextField.text, @"age" : _ageTextField.text, @"sex" : _sexTextField.text};
[self.navigationController popViewControllerAnimated:YES];
_retDict(dict);
}
}
- (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
DogViewController.h
#import <UIKit/UIKit.h> #import "Person.h" #import "Dog.h" @interface DogViewController : UIViewController @property(nonatomic, strong) Person * person; @property(nonatomic, strong) NSManagedObjectContext * context; @end
//
// DogViewController.m
#import "DogViewController.h"
#import "AddDogViewController.h"
@interface DogViewController () <UITableViewDelegate,UITableViewDataSource>
{
UITableView * _tableView;
NSArray * _dataArray;
}
@end
@implementation DogViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.title = @"宠物";
self.view.backgroundColor = [UIColor whiteColor];
_tableView = [[UITableView alloc]initWithFrame:self.view.bounds style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
[self.view addSubview:_tableView];
//排序
NSSortDescriptor * sortDes = [[NSSortDescriptor alloc]initWithKey:@"name" ascending:NO];
_dataArray = [_person.pet sortedArrayUsingDescriptors:@[sortDes]];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemAdd target:self action:@selector(addDog)];
}
-(void)addDog
{
AddDogViewController * addDog = [[AddDogViewController alloc] init];
[self.navigationController pushViewController:addDog animated:YES];
[addDog setRetDict:^(NSDictionary * dict) {
Dog * dog = [NSEntityDescription insertNewObjectForEntityForName:@"Dog" inManagedObjectContext:_context];
dog.name = dict[@"name"];
dog.age = [NSNumber numberWithInt:[dict[@"age"] intValue]];
dog.type = dict[@"type"];
[_person addPetObject:dog];
[_context save:nil];
NSSortDescriptor *sd = [[NSSortDescriptor alloc]initWithKey:@"name" ascending:NO];
_dataArray = [_person.pet sortedArrayUsingDescriptors:@[sd]];
[_tableView reloadData];
}];
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString * cellid = @"celliddog";
UITableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:cellid];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellid];
}
cell.textLabel.text = [_dataArray[indexPath.row] name];
NSString * ageStr = [NSString stringWithFormat:@"%i", [[_dataArray[indexPath.row] age] intValue]];
cell.detailTextLabel.text = [NSString stringWithFormat:@"age:%@", ageStr];
return cell;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _dataArray.count;
}
- (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
AddDogViewController.h 和 AddDogViewController.m中的代码这里不再粘贴,可以参照AddPersonViewController
四个Person和四个Dog文件都是自动生成的,里面暂时什么也不需要动。
效果图: