
-
创建项目时选择
image.png
-
创建实体(选择项目中的.xcdatamodeld后缀文件)
image.png
-
创建实体类
image.png
- 将AppDelegate中的coreData相关剪切到自己新建的类中(CoreDataStack)里面有增删改查的方法
//
// CoreDataStack.m
// MyCoreDataDemo
//
// Created by 陈帆 on 2019/11/6.
// Copyright © 2019 陈帆. All rights reserved.
//
#import "CoreDataStack.h"
#import "User+CoreDataClass.h"
#define tableName @"User"
@interface CoreDataStack()
/// 文件目录
@property(nonatomic, copy) NSString *documentDir;
/// 上下文
@property(nonatomic, retain) NSManagedObjectContext *context;
@property(nonatomic, retain) NSPersistentStoreCoordinator *persistentStoreCoordinator;
@property(nonatomic, copy) NSManagedObjectModel *managedObjectModel;
@end
@implementation CoreDataStack
#pragma mark - Core Data stack
@synthesize persistentContainer = _persistentContainer;
/// 单例
+ (instancetype)shareInstance {
static CoreDataStack *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance =[[CoreDataStack alloc] init];
});
return instance;
}
- (NSPersistentCloudKitContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
@synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentCloudKitContainer alloc] initWithName:@"MyCoreDataDemo"];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation 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.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(@"Unresolved error %@, %@", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;
}
#pragma mark - Core Data Saving support
- (void)saveContext {
NSManagedObjectContext *context = self.persistentContainer.viewContext;
NSError *error = nil;
if ([context hasChanges] && ![context save:&error]) {
// Replace this implementation 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();
}
}
- (NSString *)documentDir {
if (!_documentDir) {
_documentDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
}
return _documentDir;
}
- (NSManagedObjectContext *)context {
if (!_context) {
// _context = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
_context = self.persistentContainer.viewContext;
}
return _context;
}
- (NSManagedObjectModel *)managedObjectModel {
if (_managedObjectModel) {
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[[NSBundle mainBundle] URLForResource:@"coreData" withExtension:@"momd"]];
}
return _managedObjectModel;
}
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator {
if (!_persistentStoreCoordinator) {
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:_managedObjectModel];
NSString *sqliteURL = [_documentDir stringByAppendingPathComponent:@"coreData.sqlite"];
NSDictionary *options = @{
NSMigratePersistentStoresAutomaticallyOption : @YES,
NSInferMappingModelAutomaticallyOption : @YES
};
NSString *failureReason = @"There was an error creating or loading the application's saved data.";
@try {
[_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:sqliteURL] options:options error:nil];
} @catch (NSException *exception) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data";
dict[NSLocalizedFailureReasonErrorKey] = failureReason;
NSError *wrappedError = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:6666 userInfo:dict];
NSLog(@"Unresolved error %@, %@", wrappedError, wrappedError.userInfo);
abort();
} @finally {
}
}
return _persistentStoreCoordinator;
}
- (User *)newUserEntity {
return [NSEntityDescription insertNewObjectForEntityForName:tableName inManagedObjectContext:self.context];
}
/// 增加用户实体
/// @param user 用户对象
- (void)addUser:(User *)user {
[self saveContext];
}
/// 获取用户列表
- (NSArray<User *> *)getUserList {
@try {
NSArray *userList = [self.context executeFetchRequest:[User fetchRequest] error:nil];
return userList;
} @catch (NSException *exception) {
NSLog(@"getUserList error:%@", exception.description);
}
}
/// 删除指定索引用户
/// @param index 索引值
- (void)deleteUser:(NSUInteger)index {
@try {
NSArray *userList = [self.context executeFetchRequest:[User fetchRequest] error:nil];
if (userList.count > 0 && index < userList.count) {
[self.context deleteObject:userList[0]];
[[CoreDataStack shareInstance] saveContext];
} else {
NSLog(@"deleteUser failed. reason:data is null or index larger array count");
}
} @catch (NSException *exception) {
NSLog(@"deleteUser error. %@", exception.description);
}
}
/// 删除所有用户
- (void)deleteAllUser {
@try {
NSArray *userList = [self.context executeFetchRequest:[User fetchRequest] error:nil];
if (userList.count > 0) {
[self.context deletedObjects];
[[CoreDataStack shareInstance] saveContext];
} else {
NSLog(@"deleteUser failed. reason:data is null");
}
} @catch (NSException *exception) {
NSLog(@"deleteUser error. %@", exception.description);
}
}
/// 更新(修改)用户
/// @param user 用户对象
- (void)updateUser:(User *)user {
@try {
NSArray *userList = [self.context executeFetchRequest:[User fetchRequest] error:nil];
for (User *tempUser in userList) {
if ([tempUser.userId isEqual:user.userId]) {
tempUser.username = user.username;
tempUser.age = user.age;
tempUser.isMan = user.isMan;
break;
}
}
[[CoreDataStack shareInstance] saveContext];
} @catch (NSException *exception) {
NSLog(@"deleteUser error. %@", exception.description);
}
}
@end
- 调用相关的增删改查方法
//
// ViewController.m
// MyCoreDataDemo
//
// Created by 陈帆 on 2019/11/6.
// Copyright © 2019 陈帆. All rights reserved.
//
#import "ViewController.h"
#import "User+CoreDataClass.h"
#import "CoreDataStack.h"
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
@property(nonatomic, strong) NSMutableArray *dataSource;
@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, weak) UIButton *addBtn;
@property(nonatomic, weak) UIButton *deleteBtn;
@property(nonatomic, weak) UIButton *modifyBtn;
@property(nonatomic, weak) UIButton *queryBtn;
@property(nonatomic, weak) UILabel *noDataTipLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setViewUI];
}
- (void)setViewUI {
// 设置增加按钮
UIButton *addBtn = [[UIButton alloc] init];
self.addBtn = addBtn;
[addBtn setTitle:@"增加" forState:UIControlStateNormal];
addBtn.backgroundColor = [UIColor blueColor];
[addBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
addBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
[addBtn addTarget:self action:@selector(addBtnClick:) forControlEvents:UIControlEventTouchUpInside];
// 设置删除按钮
UIButton *deleteBtn = [[UIButton alloc] init];
self.deleteBtn = deleteBtn;
[deleteBtn setTitle:@"删除" forState:UIControlStateNormal];
deleteBtn.backgroundColor = [UIColor blueColor];
[deleteBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
deleteBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
[deleteBtn addTarget:self action:@selector(deleteBtnClick:) forControlEvents:UIControlEventTouchUpInside];
// 设置修改按钮
UIButton *modifyBtn = [[UIButton alloc] init];
self.modifyBtn = modifyBtn;
[modifyBtn setTitle:@"修改" forState:UIControlStateNormal];
modifyBtn.backgroundColor = [UIColor blueColor];
[modifyBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
modifyBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
[modifyBtn addTarget:self action:@selector(modifyBtnClick:) forControlEvents:UIControlEventTouchUpInside];
// 设置查询按钮
UIButton *queryBtn = [[UIButton alloc] init];
self.queryBtn = queryBtn;
[queryBtn setTitle:@"查询" forState:UIControlStateNormal];
queryBtn.backgroundColor = [UIColor blueColor];
[queryBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
queryBtn.titleLabel.font = [UIFont systemFontOfSize:14.0];
[queryBtn addTarget:self action:@selector(queryBtnClick:) forControlEvents:UIControlEventTouchUpInside];
// 没有数据提醒
UILabel *noDataTipLabel = [[UILabel alloc] init];
self.noDataTipLabel = noDataTipLabel;
noDataTipLabel.text = @"没有数据啦";
noDataTipLabel.textColor = [UIColor lightGrayColor];
noDataTipLabel.textAlignment = NSTextAlignmentCenter;
noDataTipLabel.font = [UIFont systemFontOfSize:14.0];
noDataTipLabel.numberOfLines = 0;
// noDataTipLabel.hidden = YES;
self.tableView.layer.masksToBounds = true;
self.tableView.layer.cornerRadius = 10;
self.tableView.backgroundColor = [UIColor groupTableViewBackgroundColor];
self.tableView.tableFooterView = [UIView new];
self.tableView.delegate = self;
self.tableView.dataSource = self;
[self.view addSubview:addBtn];
[self.view addSubview:modifyBtn];
[self.view addSubview:deleteBtn];
[self.view addSubview:queryBtn];
self.tableView.backgroundView = self.noDataTipLabel;
[self.view addSubview:self.tableView];
self.view.backgroundColor = [UIColor darkGrayColor];
}
- (void)viewDidLayoutSubviews {
[super viewDidLayoutSubviews];
// 设置布局适配
int btnWidth = 70, btnHeight = 30, gapXY = 20;
[self.addBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_top).with.offset(gapXY*2);
make.right.equalTo(self.view.mas_centerX).with.offset(-gapXY/2);
make.width.mas_equalTo(btnWidth);
make.height.mas_equalTo(btnHeight);
}];
[self.deleteBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.view.mas_top).with.offset(gapXY*2);
make.left.equalTo(self.view.mas_centerX).with.offset(gapXY/2);
make.width.mas_equalTo(btnWidth);
make.height.mas_equalTo(btnHeight);
}];
[self.modifyBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.addBtn.mas_bottom).with.offset(gapXY);
make.right.equalTo(self.view.mas_centerX).with.offset(-gapXY/2);
make.width.mas_equalTo(btnWidth);
make.height.mas_equalTo(btnHeight);
}];
[self.queryBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.deleteBtn.mas_bottom).with.offset(gapXY);
make.left.equalTo(self.view.mas_centerX).with.offset(gapXY/2);
make.width.mas_equalTo(btnWidth);
make.height.mas_equalTo(btnHeight);
}];
[self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.modifyBtn.mas_bottom).with.offset(gapXY);
make.left.mas_equalTo(gapXY);
make.right.mas_equalTo(-gapXY);
make.bottom.equalTo(self.view.mas_bottom).with.offset(-gapXY);
}];
[self.noDataTipLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.centerX.mas_equalTo(self.tableView.mas_centerX);
make.centerY.mas_equalTo(self.tableView.mas_centerY);
make.width.mas_equalTo(self.tableView.mas_width);
make.height.mas_equalTo(btnHeight);
}];
}
// MARK: - selector action funcation
// MARK: 增加按钮响应
- (void)addBtnClick:(UIButton *)sender {
if (@available(iOS 13.0, *)) {
User *user = [[CoreDataStack shareInstance] newUserEntity];
user.userId = [NSString stringWithFormat:@"%f", [[NSDate date] timeIntervalSince1970]];
user.username = [NSString stringWithFormat:@"张三%ld", random()];
user.age = 18;
user.createTime = [NSDate date];
user.income = [[NSDecimalNumber alloc] initWithFloat:1233.04338];
user.isMan = YES;
user.userIcon = @"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1573042496310&di=d6b4363fe0bb7455d97672b4d5d0e316&imgtype=jpg&src=http%3A%2F%2Fimg1.imgtn.bdimg.com%2Fit%2Fu%3D4232323981%2C903032036%26fm%3D214%26gp%3D0.jpg";
[[CoreDataStack shareInstance] addUser:user];
// 查询
[self queryBtnClick:nil];
} else {
// Fallback on earlier versions
}
}
// MARK: 删除按钮响应
- (void)deleteBtnClick:(UIButton *)sender {
if (@available(iOS 13.0, *)) {
[[CoreDataStack shareInstance] deleteUser:0];
[self queryBtnClick:nil];
} else {
// Fallback on earlier versions
}
NSLog(@"删除成功");
}
// MARK: 需改按钮响应
- (void)modifyBtnClick:(UIButton *)sender {
if (self.dataSource.count > 0) {
[self.tableView selectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0] animated:true scrollPosition:UITableViewScrollPositionTop];
[self tableView:self.tableView didSelectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
}
}
// MARK: 查询按钮响应
- (void)queryBtnClick:(UIButton *)sender {
[self.dataSource removeAllObjects];
if (@available(iOS 13.0, *)) {
NSArray *userList = [[CoreDataStack shareInstance] getUserList];
if (userList.count > 0) {
[self.dataSource addObjectsFromArray:userList];
}
} else {
// Fallback on earlier versions
}
[self.tableView reloadData];
}
// MARK: - UITableView Delegate
// MARK: section Count
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
// MARK: row count in section
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
self.noDataTipLabel.hidden = self.dataSource.count > 0;
return self.dataSource.count;
}
// MARK: cell content
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"cell"];
cell.detailTextLabel.numberOfLines = 0;
}
// 填充数据
User *user = self.dataSource[indexPath.row];
cell.textLabel.text = user.username;
cell.detailTextLabel.text = [NSString stringWithFormat:@"age:%d\ncreateTime:%@\nincome:%@\nisMan:%@\nuserId:%@", user.age, user.createTime, user.income, user.isMan ? @"YES":@"NO", user.userId];
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:user.userIcon] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) {
if (image) {
// 调整图片大小
CGSize imageSize = CGSizeMake(70, 70);
UIGraphicsBeginImageContextWithOptions(imageSize, NO, UIScreen.mainScreen.scale);
[image drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)];
cell.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
}
}];
return cell;
}
// MARK: cell height
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 140;
}
// MARK: did selected
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"请输入个人信息" preferredStyle:UIAlertControllerStyleAlert];
// selected user
User *user = self.dataSource[indexPath.row];
//增加确定按钮;
[alertController addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//获取第1个输入框;
UITextField *userNameTextField = alertController.textFields.firstObject;
if (![userNameTextField.text isEqual:@""] && ![userNameTextField.text isEqual:user.username]) {
user.username = userNameTextField.text;
}
//获取第2个输入框;
UITextField *ageTextField = [alertController.textFields objectAtIndex:1];
if (![ageTextField.text isEqual:@""] && ![ageTextField.text isEqual:[NSString stringWithFormat:@"%d", user.age]]) {
user.age = [ageTextField.text intValue];
}
//获取第3个输入框;
UITextField *sexField = alertController.textFields.lastObject;
if (![sexField.text isEqual:@""]) {
user.isMan = ![sexField.text isEqual:@"0"];
}
if (@available(iOS 13.0, *)) {
[[CoreDataStack shareInstance] updateUser:user];
} else {
// Fallback on earlier versions
}
[self.tableView reloadData];
}]];
// 增加取消按钮
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"取消");
[self.tableView deselectRowAtIndexPath:indexPath animated:true];
}]];
//定义第一个输入框;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"请输入用户名";
}];
//定义第二个输入框;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"请输入年龄";
}];
//定义第三个输入框;
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"性别";
}];
[self presentViewController:alertController animated:true completion:nil];
}
// MARK: - get / set 方法
/// get dataSource
- (NSMutableArray *)dataSource {
if (!_dataSource) {
_dataSource = [[NSMutableArray alloc] init];
}
return _dataSource;
}
/// get tableview
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
}
return _tableView;
}
@end
附件(GitHub地址):https://github.com/MacleChen/MyCoreDataDemo.git
网友评论