初始化
- (NSManagedObjectContext *)context {
if (_context == nil) {
// 创建上下文对象,并发队列设置为主队列
_context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
// 创建托管对象模型,并使用Student.momd路径当做初始化参数
// .xcdatamodeld文件 编译之后变成.momd文件 (.mom文件)
NSURL *modelPath = [[NSBundle mainBundle] URLForResource:@"Test" withExtension:@"momd"];
NSManagedObjectModel *model = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelPath];
// 创建持久化存储调度器
NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:model];
// 创建并关联SQLite数据库文件,如果已经存在则不会重复创建
NSString *dataPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject;
dataPath = [dataPath stringByAppendingFormat:@"/%@.sqlite",@"CPStudent"];
// 创建
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:options error:nil];
// 上下文对象设置属性为持久化存储器
_context.persistentStoreCoordinator = coordinator;
}
return _context;
}
- (NSPersistentContainer *)persistentContainer {
// 如果已经存在持久容器,直接返回
if (_persistentContainer != nil) {
return _persistentContainer;
}
// 创建持久容器,通常与你的数据模型同名
_persistentContainer = [[NSPersistentContainer alloc] initWithName:@"test"];
// 完成持久容器的加载
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort(); // 处理初始化错误
}
}];
return _persistentContainer;
}
- (void)initCoreData {
NSPersistentContainer *container = [self persistentContainer];
[container loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error) {
NSLog(@"Error loading Core Data store: %@, %@", error, error.userInfo);
abort(); // 处理初始化错误
}
NSManagedObjectContext *context = [self persistentContainer].viewContext;
NSManagedObject *newStudent = [NSEntityDescription insertNewObjectForEntityForName:@"newStudent" inManagedObjectContext:context];
[newStudent setValue:@"liming" forKey:@"name"];
[newStudent setValue:@(11) forKey:@"age"];
[newStudent setValue:@(100001) forKey:@"numebr"];
NSError *addError;
if (![context save:&addError]) {
NSLog(@"Error saving context: %@", addError.localizedDescription);
}
}];
}
增
- (CPStudent *)insertStudentData {
NSError *error = nil;
// 开始创建托管对象,并指明好创建的托管对象所属实体名
CPStudent * student = [NSEntityDescription insertNewObjectForEntityForName:@"CPStudent" inManagedObjectContext:self.context];
//2.根据表Student中的键值,给NSManagedObject对象赋值
student.name = [NSString stringWithFormat:@"Mr-%d",arc4random() % 100];
student.age = arc4random() % 20;
student.sex = arc4random() % 2 == 0 ? @"男" : @"女" ;
student.height = arc4random() % 180;
student.number = arc4random() % 100;
student.father = @"aaa";
student.studentNumber = arc4random() % 100;
if ([self.context hasChanges] && ![self.context save:&error]) {
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
return nil;
} else {
NSLog(@"插入数据成功");
}
return student;
}
删
- (void)delete:(NSArray *)delStudents {
// 获取数据的请求对象,指明对实体进行删除操作
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CPStudent"];
[delStudents enumerateObjectsUsingBlock:^(CPStudent *obj, NSUInteger idx, BOOL *stop) {
// 通过创建谓词对象,然后过滤掉符合要求的对象,也就是要删除的对象
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"number = %d",obj.number];
request.predicate = predicate;
// 通过执行获取操作,找到要删除的对象即可
NSError *error = nil;
NSArray<CPStudent *> *students = [self.context executeFetchRequest:request error:&error];
// 开始真正操作,一一遍历,遍历符合删除要求的对象数组,执行删除操作
[students enumerateObjectsUsingBlock:^(CPStudent *obj, NSUInteger idx, BOOL *stop) {
[self.context deleteObject:obj];
}];
// 错误处理
if (error) {
NSLog(@"删除失败");
} else {
NSLog(@"删除成功");
}
}];
// 最后保存数据,保存上下文。
if (self.context.hasChanges) {
[self.context save:nil];
}
}
改
- (void)modify:(NSArray *)modifyStudents {
// 获取数据的请求对象,指明对实体进行删除操作
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CPStudent"];
[modifyStudents enumerateObjectsUsingBlock:^(CPStudent *obj, NSUInteger idx, BOOL *stop) {
// 通过创建谓词对象,然后过滤掉符合要求的对象,也就是要删除的对象
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"number = %d",obj.number];
request.predicate = predicate;
// 通过执行获取操作,找到要删除的对象即可
NSError *error = nil;
NSArray<CPStudent *> *students = [self.context executeFetchRequest:request error:&error];
// 开始真正操作,一一遍历,遍历符合删除要求的对象数组,执行删除操作
[students enumerateObjectsUsingBlock:^(CPStudent *obj, NSUInteger idx, BOOL *stop) {
obj.age += 1;
obj.sex = [obj.sex isEqualToString:@"男"] ? @"女" : @"男";
}];
// 错误处理
if (error) {
NSLog(@"改失败");
} else {
NSLog(@"改成功");
}
}];
// 最后保存数据,保存上下文。
if (self.context.hasChanges) {
[self.context save:nil];
}
}
查
- (NSArray<CPStudent *> *)fetchTapStudentData {
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"CPStudent"];
// 执行获取操作,获取所有Student托管对象
NSError *error = nil;
NSArray<CPStudent *> *students = [self.context executeFetchRequest:request error:&error];
if (error) {
NSLog(@"失败");
} else {
NSLog(@"查找数据成功");
}
return students;
}
数据迁移
轻数据迁移
适用场景:
- 添加、删除一个表或者属性
- 属性值可空与不可空的改变
- 重命名表或者属性
- 单一的一次迁移(如果出现多次版本迁移要一起做,就要进行逐步迁移,不能用轻数据迁移)
//请求自动轻量级迁移
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption,
nil];
NSError *error = nil;
[coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:newDataPath] options:options error:nil];
自定义数据迁移
创建MappingModel在指定映射。使用NSEntityMigrationPolicy类来指定迁移策略。
- 使用NSPersistentStoreCoordinator持久化调度器来获取当前版本model
- 使用NSManagedObjectModel获取最新model
- 对本版本,渐进式迁移。