KVC是什么在这里不做过多的阐述,我们来看一下KVC在项目中的使用。项目中我们会经常用到Model类,其实KVC最常见的用法就是用在给这些Model类赋值的时候,(至少目前我做了这么好多项目,也就是这个地方最常用)。
经常见到的情况:
1.在给UITableView的每个cell添加数据的时候,我们用一个Model类来对应一个cell上的数据,当我们请求完数据后,通常后台返回给我们的是N个Cell上的数据,保存在数组中,而每个cell上的数据都是一个字典,这个时候普通的攻城狮会直接把这个数组拿到自己的数组中,然后在- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath这个方法中,如下操作:
操作1.1
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString * ce = @"id";
CommentTableViewCell * cell = [tableView dequeueReusableCellWithIdentifier:ce];//自定义的Cell
if (!cell) {
cell = [[CommentTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ce];
}
//显示到cell上
NSDictionary * dic = [_tableArray objectAtIndex:indexPath.row];//从数组中取出字典
cell.name.text = [dic objectForKey:@"username"];//各种objectForKey开始给cell赋值
cell.time.text = [dic objectForKey:@"dateline"];
cell.comment.text = [dic objectForKey:@"message"];
NSString * conmmentNum = [NSString stringWithFormat:@" ---全部评论(%lu)",(unsigned long)_tableArray.count];
[_commentLabel setText:conmmentNum];
[cell.image sd_setImageWithURL:[NSURL URLWithString:[dic objectForKey:@"headimg"]] placeholderImage:[UIImage imageNamed:@"wode1_06.png"]];
return cell;
}
而高级一点的攻城狮会在拿到数据的时候,做如下处理:
操作2.1
self.tableArray = [[NSMutableArray alloc] init];//该数组用来给UITableViw放数据,应该及早初始化。
NSArray * array = [[object objectForKey:@"Variables"] objectForKey:@"value"];//该数组是拿到后台数据经过编码处理的数组,做临时用
for (NSDictionary * dic in array) {
Doctor * doctor = [[Doctor alloc] init];
[doctor setValuesForKeysWithDictionary:dic];//**利用KVC给Doctor对象赋值**
[_tableArray addObject:doctor];//将doctor对象保存在UITableView的数组中
[self.tableView reloadData];
}
然后在- (UITableViewCell )tableView:(UITableView )tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath这个方法中,如下操作:
操作2.2
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *str = @"doctorCell";
DoctorTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:str];
if (!cell) {
cell = [[[NSBundle mainBundle] loadNibNamed:@"MyDoctorTableViewCell" owner:self options:nil]lastObject];//该cell是用xib创建的
}
[cell configureForModel:[tableArray objectAtIndex:indexPath.row]];//在MyDoctorTableViewCell中写了一个接口,在这里调用,这个接口的实现请继续往下看
// Configure the cell...
return cell;
}
再然后,再在MyDoctorTableViewCell.m里做如下操作:
操作2.3
- (void)configureForModel:(Doctor *)doctor{
// [self.doctorIma setImageWithURL:[NSURL URLWithString:doctor.headimg] placeholderImage:nil];
self.doctorNameLab.text = doctor.realname;
self.doctorTitleLab.text = doctor.title;
self.achievementLab.text = doctor.achievement;
[self.doctorIma sd_setImageWithURL:[NSURL URLWithString:doctor.headimg] placeholderImage:nil];
self.doctorIma.layer.cornerRadius = 55/2;
self.doctorIma.layer.masksToBounds = YES;
self.hospitalLab.text = doctor.hospital;
}
其实KVC在这里最重要的一步就是操作2.1里面的[doctor setValuesForKeysWithDictionary:dic];
这段话。这句话就是将字典dic的每个key的Value赋值给doctor对象的每个属性,当然,如果说这个字典里的某个key是类似于oc里的关键字,比如说“id”,(后台的攻城狮很喜欢用这个),要知道doctor这个类肯定不能某个熟悉是id,这个时候,就需要用到KVC的另一个方法
(void)setValue:(id)value forUndefinedKey:(NSString *)key
在Doctor.m中做如下操作:
操作2.4
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"id"]) {//判断是否有key是关键字id
self.doctorID = value;//用自己命名的属性来接收这个id
}
if ([key isEqualToString:@"title"]) {//如果你觉得后台的某个key不符合你的性格或者这个类的属性,你也可以自己搞
self.stitle = value;
}
}
其实操作2.4就是一个容错的处理。
总结一下,为什么要这样做,这样做是不是看起来灰常复杂,但是这样做的目的就是让代码更清晰明白,耦合更低,维护更加方便,当然如果没有做过几个项目可能体会不大,但是当你一步一步深入编程之后,你会觉得这样写更舒服,当然还有比我这个写法更佳好的写法,还请大神们能指教。