宽容他人,放过自己。

Core Data自我总结

Posted on By anchoriteFili

相关链接


coreData第一版_只有简单的StudentEntity coreData第二版_添加了ClassEntity

CoreData第一版


151913077951772.png

前期操作

首先创建新文件Use Core Data勾选

130854481447720.png

在AppDelegate中就会出现附加代码

#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
#pragma mark 被管理的数据上下文 作用:插入数据,查询数据,删除数据
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#pragma mark 被管理的数据模型:数据库所有表格或数据结构偶,包含各种实体的定义信息 作用:添加实体的属性,建立属性之间关系
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#pragma mark 持久化存储助理,相当于数据库的连接器 作用:设置数据存储的名字,位置,存储方式,和存储时机
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

#pragma mark 保存数据岛持久层(数据库)
- (void)saveContext;
#pragma mark 应用程序沙盒下的Documents目录路径
- (NSURL *)applicationDocumentsDirectory;

@end

AppDelegate.m中的代码不用管

新添加Core Data_Data Model文件

130859369416491.png

在文件中点击Add Entity,创建新的实体

130902296763020.png

对每个Entity进行赋值

130904282385832.png

选中CoreData_self.xcdatamodeld,点击Editor,点击最长的createManager….拉出实体属性

130906433791845.png

130906535666067.png

代码部分

StudentTableViewController.h中添加context和stuArray,懒加载实现

#import <UIKit/UIKit.h>

@interface StudentTableViewController : UITableViewController

#pragma mark 创建一个被管理的数据上下文,用于插入数据,查询数据,删除数据
@property (nonatomic,retain) NSManagedObjectContext *context;
#pragma mark 创建一个由实体组成的数据,用于传值
@property (nonatomic,retain) NSMutableArray *stuArray;

@end

.m中实现懒加载
#pragma mark 懒加载初始化stuArray
- (NSMutableArray *)stuArray {
    if (_stuArray == nil) {
        _stuArray = [NSMutableArray array];
    }
    return _stuArray;
}

#pragma mark 懒加载获取context
- (NSManagedObjectContext *)context {
    AppDelegate *myDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    if (_context == nil) {
        _context = myDelegate.managedObjectContext;
    }
    return _context;
}

实现向数据库添加的功能

#pragma mark 添加学生点击事件
- (IBAction)addStudentClick:(UIBarButtonItem *)sender {
    
//    创建实体描述文件_在context中有一个名字叫StudentEntity的实体
    NSEntityDescription *myEntityDes = [NSEntityDescription entityForName:@"StudentEntity" inManagedObjectContext:self.context];
    
//    生成一个实体_实体开辟空间,并和描述文件一起插入到context上下文中
    StudentEntity *stu = [[StudentEntity alloc] initWithEntity:myEntityDes insertIntoManagedObjectContext:_context];
    
//    给实体配置属性
    NSArray *names = @[@"赤",@"橙",@"黄",@"绿",@"青",@"蓝"];
    stu.name = names[arc4random() % names.count];
    stu.age = [NSNumber numberWithInteger:arc4random()%100];
    stu.gender = @"男";
    stu.creatTime = [NSDate date];
    
//    上下文保存_将承载有实体描述文件和实体的context同过save方法存储到数据库
    BOOL result = [_context save:nil];
    if (result) {
//        如果存储成功,则将stu实体直接赋值给实体数组,用于传值,刷新tableView
        [self.stuArray addObject:stu];
        [self.tableView reloadData];
    }
}

数据库中的查找功能

#pragma mark 查找_在显示的时候从数据库中直接调取数据,可以实现上次下线儿时的状态
- (void)viewDidLoad {
    [super viewDidLoad];
    
//    查找条件_根据实体名发送查找申请 fetch_查找,取得
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StudentEntity"];
    
//    执行查找,返回结果_向context发出执行取出请求命令,从数据库中取出所有的有共同实体名的实体,组成数组
    NSArray *array = [self.context executeFetchRequest:request error:nil];
    
//    将取出的实体数组赋值给用于显示的stuArray,传到cell显示
    [self.stuArray addObjectsFromArray:array];
    [self.tableView reloadData];
    
}

改的实现

#pragma mark 修改内容
- (IBAction)saveEdit:(UIBarButtonItem *)sender {
    
    AppDelegate *myDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
//    对指定位置的实体进行重新赋值
    _student.name = self.nameTextField.text;
    _student.age = [NSNumber numberWithInt:[self.ageTextField.text intValue]];
    _student.gender = self.genderTextField.text;
//    然后通过save方法,至今将新的值存进去
    [myDelegate.managedObjectContext save:nil];
    
}

对cell进行赋值

#pragma mark 对cell进行赋值
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    StudentTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"stuCell" forIndexPath:indexPath];
//    进行传值,
    StudentEntity *stu = _stuArray[indexPath.row];
    cell.nameLabel.text = stu.name;
    cell.ageLabel.text = [NSString stringWithFormat:@"%@",stu.age];
//    description:Returns a string representation of the receiver.
    cell.createTimeLabel.text = [stu.creatTime description];
    [cell.imageView setImage:[UIImage imageNamed:@"呵呵.gif"]];
    
    // Configure the cell...
    
    return cell;
}

cell的行删除的实现

#pragma mark 可以对行进行编辑
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the specified item to be editable.
    return YES;
}

#pragma mark 编辑方式的选择
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
//    删除编辑方式
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        
//       先通过context删除数据库中的这一行的数据
        [_context deleteObject:[_stuArray objectAtIndex:indexPath.row]];
        
//        再删除stuArray里对应的元素
        [_stuArray removeObjectAtIndex:indexPath.row];
        [_context save:nil];
//        删除自带方法,删除indexPath所对应的row
        [tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
    } else if (editingStyle == UITableViewCellEditingStyleInsert) {
//        插入编辑方式
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}

行移动的实现

#pragma mark 移动的实现
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath {
}

#pragma mark 可以移动
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath {
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}

CoreData第二版


151914539982992.png

前期操作

创建新版本资料

151923578267616.png

在右侧的Model Version中添加使用最新的版本

151925107015319.png

实现两个实体之间的链接,编写两个实体的Relationship内容

在ClassEntity中,设置Relationships,并与StudentEntity建立一对多得关系

151928142481712.png

在右侧的属性栏里设置Relationships,设置成To Many,一对多关系

151930582637002.png

在StudentEntity中,设置Relationships

151932265291538.png

在右侧的属性栏里,设置StudentEntity的属性,To One_一对一的关系

151933578883826.png

然后将实体从新拉出来,以代码的形式显示出来

151935259041904.png

151935356859481.png

151935517635470.png

替换掉旧的代码实体

151936238884689.png

新的实体代码里有联系两者的关系代码出现,如果不出现则手动删掉代码实体,重复上边添加过程

代码部分

ClassEntity.h中有链接两个实体的方法出现

#warning 新版本有了方法
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>

@class StudentEntity;

@interface ClassEntity : NSManagedObject

@property (nonatomic, retain) NSString * classname;
@property (nonatomic, retain) NSNumber * stucount;
@property (nonatomic, retain) NSSet *stuOfClass;
@end

@interface ClassEntity (CoreDataGeneratedAccessors)

- (void)addStuOfClassObject:(StudentEntity *)value;
- (void)removeStuOfClassObject:(StudentEntity *)value;
- (void)addStuOfClass:(NSSet *)values;
- (void)removeStuOfClass:(NSSet *)values;

@end

先在AppDlegate.m中设置添加入新版本,创建新版本的数据库,并让以后的数据都添加到新的版本中

- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
    // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it.
#warning 新版本添加,作用:将数据添加到新表中,不再添加到旧表中
    NSDictionary *options = @{NSMigratePersistentStoresAutomaticallyOption: [NSNumber numberWithBool:YES],NSInferMappingModelAutomaticallyOption: [NSNumber numberWithBool:YES]};
    
    if (_persistentStoreCoordinator != nil) {
        return _persistentStoreCoordinator;
    }
    
    // Create the coordinator and store
    
    _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
    NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Coredata.sqlite"];
    NSError *error = nil;
    NSString *failureReason = @"There was an error creating or loading the application's saved data.";
#warning 将options添加到此
    if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
        // 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();
    }
    
    return _persistentStoreCoordinator;
}

添加ClassTableViewController,实现新的页面的添加

在ClassTableViewController中添加两个属性,context和classArray,并进行懒加载

//桥梁的作用
@property (nonatomic,retain) NSManagedObjectContext *context;
//cell中传值的作用
@property (nonatomic,retain) NSMutableArray *classArray;

#pragma mark 懒加载
#warning 用self.classArray,会崩
- (NSMutableArray *)classArray {
    if (!_classArray) {
        _classArray = [NSMutableArray array];
    }
    return _classArray;
}
#warning 注意appDelegate的生成
- (NSManagedObjectContext *)context {
    AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
    
    if (!_context) {
        _context = appDelegate.managedObjectContext;
    }
    return _context;
}

实现班级的添加功能

#pragma mark 添加班级点击事件
- (IBAction)addClassClick:(UIBarButtonItem *)sender {
    
//   创建描述文件
    NSEntityDescription *myEntity = [NSEntityDescription entityForName:@"ClassEntity" inManagedObjectContext:self.context];
//    生成一个实体
    ClassEntity *classEntity = [[ClassEntity alloc] initWithEntity:myEntity insertIntoManagedObjectContext:self.context];
//    给实体配置属性
    classEntity.classname = @"研三";
    classEntity.stucount = @48;
//    上下文保存
    BOOL result = [_context save:nil];
    
    if (result) {
        [self.classArray addObject:classEntity];
        [self.tableView reloadData];
    }
    
}

在StudentTableViewController.h中添加属性currentClass,用于push是传值

#pragma mark 添加currentClass用于push时传值
@property (nonatomic,retain) ClassEntity *currentClass;

在prepareForSegue:sender:方法中实现传值的对StudentTableViewController传值的作用

#pragma mark 实现对StudentTableViewController的传值
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
    
//    根据segue来确定目标VC
    StudentTableViewController *stuVC = [segue destinationViewController];
//    对sender进行强制转换成cell
    ClassTableViewCell *cell = (ClassTableViewCell *)sender;
//    再根据cell获取当前cell的indexPath
    NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];
//    根据indexPath进行传值
    stuVC.currentClass = _classArray[indexPath.row];
    
}

在StudentTableViewController.m中,添加学生并将学生保存到数据库的中间,设置学生添加到的班级

#pragma mark 添加学生点击事件
- (IBAction)addStudentClick:(UIBarButtonItem *)sender {
    
//    创建实体描述文件
    NSEntityDescription *myEntity = [NSEntityDescription entityForName:@"StudentEntity" inManagedObjectContext:self.context];
//    生成一个实体
    StudentEntity *stu = [[StudentEntity alloc] initWithEntity:myEntity insertIntoManagedObjectContext:_context];
//    给实体配置属性
    NSArray *name = @[@"小王",@"小李",@"小黄",@"小绿",@"小紫",@"小青"];
    stu.name = name[arc4random()%name.count];
    stu.age = [NSNumber numberWithInteger:arc4random() % 100];
    stu.gender = @"男";
    stu.createTime = [NSDate date];
    
#warning 设置添加到的班级,这样学生就背分到指定的班级下了,班级之间学生就不会相互影响了
    [stu setClassOfStu:_currentClass];
//    上下文保存
    BOOL result = [_context save:nil];
    if (result) {
        [self.stuArray addObject:stu];
        [self.tableView reloadData];
    }
}

在查找学生的过程中,加上断言和排序,这样每个班级查出来的学生就都不一样了

#pragma mark 实现查找功能
- (void)viewDidLoad {
    [super viewDidLoad];
//    查找条件
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"StudentEntity"];
    
//    根据班级查找学生,添加断言
    if (_currentClass) {
#pragma mark 断言,相当于数据库中的where,classOfStu是Relationsships中的第一个
        NSPredicate *predicate = [NSPredicate predicateWithFormat:@"classOfStu == %@",_currentClass];
//        在查找申请中添加断言(where)
        [request setPredicate:predicate];
    }
    
#pragma mark 添加排序,根据age排序
    NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"age" ascending:YES];
//    将sortDescriptor按age排好序后转化成数组,加入申请命令
    [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
    
//    执行查找,返回结果
    NSArray *array = [self.context executeFetchRequest:request error:nil];
//    
    [self.stuArray addObjectsFromArray:array];
    [self.tableView reloadData];
    
}