CoreData的使用
1 #import "ViewController.h" 2 #import "Person.h" 3 4 @interface ViewController () <UITableViewDelegate,UITableViewDataSource> { 5 UITableView *_tableView; 6 NSMutableArray *_dataArray; 7 8 UITextField *_nameTextField; 9 UITextField *_ageTextField; 10 11 NSManagedObjectContext *_context; //上下文对象 我们对数据库的操作都是通过这个上下对象进行的 12 13 14 int _selectedRow; //记录选择哪一个cell 15 16 } 17 18 @end 19 20 @implementation ViewController 21 22 - (void)viewDidLoad { 23 [super viewDidLoad]; 24 25 [self readyCoreData]; 26 27 [self createUI]; 28 29 } 30 31 //准备CoreData方法 32 - (void)readyCoreData { 33 34 //1.1创建momd(编译后的扩展名)文件路径 1.2在这个文件中创建Person模型(实体) 1.3创建与实体(模型)对应的数据模型类,此类必须继承自NSManagedObject 35 NSString *path = [[NSBundle mainBundle] pathForResource:@"Model" ofType:@"momd"]; 36 37 //在操作之前 别忘记导入CorData.framework 通过path转url对象,将momd文件中的所有的模型(实体)取出放入到NSManagedObjectModel创建的对象中 38 //作用:添加实体的属性,建立属性之间的关系 39 NSManagedObjectModel *objectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:[NSURL fileURLWithPath:path]]; 40 41 //2.准备数据库路径 最后后缀db 或者rdb都可以 42 NSString *dataPath = [NSString stringWithFormat:@"%@/Documents/myCoreData.db",NSHomeDirectory()]; 43 NSLog(@"dataPath:%@",dataPath); 44 45 //3.创建持久化存储协调器 相当于数据库的连接器 46 //作用:设置数据存储的名字,位置,存储方式和存储时机 47 NSPersistentStoreCoordinator *coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:objectModel]; 48 49 //4.关联数据库 50 //4.1 关联类型 在iOS开发中一般都是SQLite (轻量级 一般用于小型移动设备)4.2配置nil 写默认即可 4.3数据库路径(字符串路径转url对象)4.4相关模式(操作) nil 4.5错误信息error对象 51 NSError *error = nil; 52 NSPersistentStore *store = [coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[NSURL fileURLWithPath:dataPath] options:nil error:&error]; 53 //判断持久化存储对象是否为空,如果为空说明数据库创建失败 54 if (store == nil) { 55 56 NSLog(@"错误信息:%@",error.localizedDescription); //打印报错信息 57 } 58 59 //5.创建上下文对象 取数据(通过CoreData将数据从数据库取出) 60 _context = [[NSManagedObjectContext alloc] init]; 61 //将上下文的持久化协调器指定到创建的属性中 (设置上下文对象的协调器) 62 _context.persistentStoreCoordinator = coordinator; 63 64 65 //查 66 //创建查找类,获取查找请求对象,相当于查询语句 根据实体名字Person得到请求对象 67 NSFetchRequest *request = [[NSFetchRequest alloc] initWithEntityName:@"Person"]; 68 //通过上下文对象执行请求 返回一个数组类型 69 NSArray *array = [_context executeFetchRequest:request error:nil]; 70 NSLog(@"array count:%ld",array.count); 71 72 //通过数组创建数组的类方法 初始化_dataArray成员变量 73 _dataArray = [NSMutableArray arrayWithArray:array]; 74 75 76 } 77 78 79 - (void)createUI { 80 81 //创建名字label 82 UILabel *nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(5, 64, 30, 30)]; 83 nameLabel.text = @"名字"; 84 nameLabel.font = [UIFont systemFontOfSize:14]; 85 [self.view addSubview:nameLabel]; 86 87 //创建一个名字的输入框 CGRectGetMaxX得到namelLabel它的最大x坐标 88 _nameTextField = [[UITextField alloc] initWithFrame:CGRectMake(CGRectGetMaxX(nameLabel.frame), 64, 90, 30)]; 89 _nameTextField.placeholder = @"请输名字"; 90 _nameTextField.borderStyle = UITextBorderStyleBezel; 91 _nameTextField.tag = 2; 92 [self.view addSubview:_nameTextField]; 93 94 //创建年龄label 95 UILabel *ageLabel = [[UILabel alloc] initWithFrame:CGRectMake(CGRectGetMaxX(_nameTextField.frame), 64, 30, 30)]; 96 ageLabel.text = @"年龄"; 97 ageLabel.font = [UIFont systemFontOfSize:14]; 98 [self.view addSubview:ageLabel]; 99 100 //创建一个年龄的输入框 101 _ageTextField = [[UITextField alloc] initWithFrame:CGRectMake(CGRectGetMaxX(ageLabel.frame), 64, 90, 30)]; 102 _ageTextField.placeholder = @"请输年龄"; 103 _ageTextField.borderStyle = UITextBorderStyleBezel; 104 _tableView.tag = 3; 105 [self.view addSubview:_ageTextField]; 106 107 108 //以下创建四个button 分别对应 增 删 改 查 109 NSArray *titles = @[@"+",@"-",@"G",@"C"]; 110 111 for (int i = 0; i < titles.count; i++) { 112 113 UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem]; 114 button.frame = CGRectMake(240 + 35*i, 64, 35, 30); 115 116 [self.view addSubview:button]; 117 118 [button setTitle:titles[i] forState:UIControlStateNormal]; 119 button.tag = i + 100; 120 [button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside]; 121 122 } 123 124 125 _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 94, self.view.frame.size.width, self.view.frame.size.height - 94) style:UITableViewStylePlain]; 126 _tableView.delegate = self; 127 _tableView.dataSource = self; 128 [self.view addSubview:_tableView]; 129 130 [_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"]; 131 132 133 } 134 135 - (void)buttonClicked:(UIButton *)button { 136 137 138 int tag = (int)button.tag - 100; 139 140 switch (tag) { 141 case 0: 142 { 143 //增加一个数据模型对象(实体结构对象或实体对象) 144 /* 145 第一个参数:增加数据对应的模型(增加一个新的数据 根据名字取) 146 第二个参数:上下文对象 注:开发中可以创建多个上下文对象管理不同的数据库,一定保证对应好哪一个上下文对象 147 */ 148 Person *person = [NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:_context]; 149 //分别设置名字和年龄 150 person.name = _nameTextField.text; 151 person.age = [NSNumber numberWithInteger:[_ageTextField.text integerValue]]; 152 153 NSError *error = nil; 154 //通过上下文对象 调用保存这个方法 传入参数error对象的地址 写入数据库 155 BOOL ret = [_context save:&error]; 156 if (ret) { //ret为真 保存成功 否则失败 157 NSLog(@"保存成功"); 158 //将person对象放入到对应的数据 最好刷新表 159 [_dataArray addObject:person]; 160 [_tableView reloadData]; 161 }else { 162 NSLog(@"保存失败:%@",error); 163 } 164 165 } 166 break; 167 case 1: 168 { 169 //取点击哪个person(点击哪个cell) 170 Person *person = _dataArray[_selectedRow]; 171 //从数据库中删除对象(模型)注:这里的删除操作只是在数据库中给了一个删除标记,并没有实际删除数据 172 [_context deleteObject:person]; 173 174 BOOL ret = [_context save:nil]; 175 if (ret) { 176 NSLog(@"删除成功"); 177 //从数组中删除数组元素(person对象) 178 [_dataArray removeObjectAtIndex:_selectedRow]; 179 //刷新表 180 [_tableView reloadData]; 181 182 }else { 183 NSLog(@"删除失败"); 184 } 185 186 } 187 break; 188 case 2: 189 { 190 //获取请求对象 理解为sqlite语句 191 NSFetchRequest *request = [[NSFetchRequest alloc] init]; 192 //首先通过NSEntityDescription创建实体对象 ,第一个参数实体名字 第二个参数上下文对象 然后给请求对象设置实体 193 [request setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:_context]]; 194 195 //谓语类 通过谓语指定查询类型 类似于FMDB where条件 这里是通过类方法格式化形式创建 196 // NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = 'Aa'"]; 197 198 199 //AND 200 // NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = 'As' AND age = 0"]; 201 202 //OR 203 204 //Sql语句 FMDB里和这里谓语条件通用 通常提交都和删除、修改、查询结合使用 205 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = 'As' OR age = 28"]; 206 207 208 //给请求对象设置谓语条件 如果不设置谓语条件会将所有数据修改 209 [request setPredicate:predicate]; 210 211 //执行请求 返回数组 212 NSArray *array = [_context executeFetchRequest:request error:nil]; 213 214 for (Person *person in array) { 215 person.name = @"不知道"; 216 person.age = [NSNumber numberWithInt:8]; 217 } 218 //保存(写回)数据库,必须要保存数据库,否则下次进入应用没有修改 219 [_context save:nil]; 220 //刷新表 221 [_tableView reloadData]; 222 223 //遍历打印一下 224 for (Person *person in _dataArray) { 225 NSLog(@"%@",person.name); 226 } 227 228 229 230 231 } 232 break; 233 case 3: 234 { 235 //查 236 //根据实体名字得到(创建)请求对象 237 NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Person"]; 238 //创建谓语条件对象 239 // NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name = '不知道'"]; 240 241 //like 像 属于一种模糊 开发中经常以什么名字开头去查询 这时候用到like , *代表任意并且B后面不管多少个字符 242 // NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like 'Be*'"]; 243 244 //以a结尾的查询 245 // NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '*a'"]; 246 247 //order by 或者group by 248 249 //名字包含有a的查询 250 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"name like '*a*'"]; 251 252 //给请求对象设置谓语条件对象 253 request.predicate = predicate; 254 //执行请求 255 NSArray *array = [_context executeFetchRequest:request error:nil]; 256 257 for (Person *person in array) { 258 NSLog(@"name:%@ age:%@",person.name,person.age); 259 } 260 261 } 262 break; 263 default: 264 break; 265 } 266 } 267 268 269 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 270 return _dataArray.count; 271 } 272 273 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 274 275 276 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath]; 277 //从数组中去person模型对象 278 Person *person = [_dataArray objectAtIndex:indexPath.row]; 279 280 cell.textLabel.text = [NSString stringWithFormat:@"姓名:%@ 年龄:%@",person.name,person.age]; 281 282 return cell; 283 284 } 285 286 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 287 //记录row (cell) 288 _selectedRow = (int)indexPath.row; 289 } 290 291 - (void)didReceiveMemoryWarning { 292 [super didReceiveMemoryWarning]; 293 // Dispose of any resources that can be recreated. 294 } 295 296 @end
1 #import <CoreData/CoreData.h> 2 3 //注:如果想用CoreData管理这个Person类创建出来的对象,必须继承自NSManagedObject,否则CoreData无法操作此类创建出来的对象 4 @interface Person : NSManagedObject 5 6 @property (nonatomic,copy) NSString *name; 7 //在数据模型中,将简单的数据类型(int float double)转换为对象 用NSNumber 8 @property (nonatomic,strong) NSNumber *age; 9 10 11 @end
1 #import "Person.h" 2 3 @implementation Person 4 5 @synthesize age; 6 @synthesize name; 7 8 @end
注意:做事有前提哦:
上图中的Teacher是以系统给的方式建的(不推荐)在Model里面添加的Person,开头一定要大写
结果是这个样的,UI设计可以改进😊