我们可以利用KVC来实现字典转模型的问题,但是必须注意的是,字典中的属性和模型中的属性必须一一对应。否则,程序会出现问题。
比如说:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
|
{
"statuses"
: [
{
"created_at"
:
"Tue May 31 17:46:55 +0800 2011"
,
"id"
: 11488058246,
"text"
:
"求关注。"
,
"source"
:
"<a href="
http:
//weibo.com" rel="nofollow">新浪微博</a>",
"favorited"
:
false
,
"truncated"
:
false
,
"in_reply_to_status_id"
:
""
,
"in_reply_to_user_id"
:
""
,
"in_reply_to_screen_name"
:
""
,
"geo"
:
null
,
"mid"
:
"5612814510546515491"
,
"reposts_count"
: 8,
"comments_count"
: 9,
"annotations"
: [],
"user"
: {
"id"
: 1404376560,
"screen_name"
:
"zaku"
,
"name"
:
"zaku"
,
"province"
:
"11"
,
"city"
:
"5"
,
"location"
:
"北京 朝阳区"
,
"description"
:
"人生五十年,乃如梦如幻;有生斯有死,壮士复何憾。"
,
"domain"
:
"zaku"
,
"gender"
:
"m"
,
"followers_count"
: 1204,
"friends_count"
: 447,
"statuses_count"
: 2908,
"favourites_count"
: 0,
"created_at"
:
"Fri Aug 28 00:00:00 +0800 2009"
,
"following"
:
false
,
"allow_all_act_msg"
:
false
,
"remark"
:
""
,
"geo_enabled"
:
true
,
"verified"
:
false
,
"allow_all_comment"
:
true
,
"verified_reason"
:
""
,
"follow_me"
:
false
,
"online_status"
: 0,
"bi_followers_count"
: 215
}
},
...
],
"previous_cursor"
: 0,
// 暂未支持
"next_cursor"
: 11488013766,
// 暂未支持
"total_number"
: 81655
}
|
其中statuses,代表的就是一个NSArray,而数组中的每一个对象就是一个NSDictionary.
一般我们直接面向字典开发的思路如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.定义一个标识
staticNSString *ID = @"cell";
// 2.去缓存池中取出可循环利用的cell
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:ID];
// 3.如果缓存中没有可循环利用的cell
if (cell ==nil) {
cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleSubtitlereuseIdentifier:ID];
}
// 4.取出对应行的微博字典
NSDictionary *statusDict =self.statuses[indexPath.row];
// 4.1展示正文
cell.detailTextLabel.text = statusDict[@"text"];
// 4.2取出对应微博的用户字典
NSDictionary *userDict = statusDict[@"user"];
//设置昵称
cell.textLabel.text = userDict[@"name"];
//取出用户头像地址
NSString *userIconUrlStr = userDict[@"profile_image_url"];
NSURL *iconUrl = [NSURLURLWithString:userIconUrlStr];
//下载图片
[cell.imageViewsd_setImageWithURL:iconUrl placeholderImage:[UIImageimageWithName:@"timeline_image_placeholder"]];
return cell;
}
但是,我们在实际的开发工作中,我们是面向模型开发的。也就是说,我们要将字典转换为一个模型。
不同点在于:
面向字典开发的话,从statuses数组中取出的时字典。
NSDictionary *statusDict = self.statuses[indexPath.row];
而面向模型开发的话,从 从 statuses数组中取出的是模型。
字典中有如下的字段,
返回值字段 | 字段类型 | 字段说明 |
---|---|---|
created_at | string | 微博创建时间 |
id | int64 | 微博ID |
mid | int64 | 微博MID |
idstr | string | 字符串型的微博ID |
text | string | 微博信息内容 |
source | string | 微博来源 |
favorited | boolean | 是否已收藏,true:是,false:否 |
truncated | boolean | 是否被截断,true:是,false:否 |
in_reply_to_status_id | string | (暂未支持)回复ID |
in_reply_to_user_id | string | (暂未支持)回复人UID |
in_reply_to_screen_name | string | (暂未支持)回复人昵称 |
thumbnail_pic | string | 缩略图片地址,没有时不返回此字段 |
bmiddle_pic | string | 中等尺寸图片地址,没有时不返回此字段 |
original_pic | string | 原始图片地址,没有时不返回此字段 |
geo | object | 地理信息字段 详细 |
user | object | 微博作者的用户信息字段 详细 |
retweeted_status | object | 被转发的原微博信息字段,当该微博为转发微博时返回 详细 |
reposts_count | int | 转发数 |
comments_count | int | 评论数 |
attitudes_count | int | 表态数 |
mlevel | int | 暂未支持 |
visible | object | 微博的可见性及指定可见分组信息。该object中type取值,0:普通微博,1:私密微博,3:指定分组微博,4:密友微博;list_id为分组的组号 |
pic_ids | object | 微博配图ID。多图时返回多图ID,用来拼接图片url。用返回字段thumbnail_pic的地址配上该返回字段的图片ID,即可得到多个图片url。 |
ad | object array | 微博流内的推广微博ID |
但是在微博模型中,我们只需要其中的部分字段,如下:
@class IWUser;
@interface IWStatus : NSObject
/**
* 微博创建时间
*/
@property (nonatomic,copy) NSString *created_at;
/**
* 字符串型的微博ID
*/
@property (nonatomic,copy) NSString *idstr;
/**
* 微博信息内容
*/
@property (nonatomic,copy) NSString *text;
/**
* 微博来源
*/
@property (nonatomic,copy) NSString *source;
/**
* 转发数
*/
@property (nonatomic,strong) NSNumber *reposts_count;
/**
* 评论数
*/
@property (nonatomic,strong) NSNumber *comments_count;
/**
* 表态数
*/
@property (nonatomic,strong) NSNumber *attitudes_count;
/**
* 微博作者的用户信息字段
*/
@property (nonatomic,strong) IWUser *user;
/**
* 被转发的原微博信息字段,当该微博为转发微博时返回
*/
@property (nonatomic,strong) IWStatus *retweeted_status;
+ (instancetype)statusWithDict:(NSDictionary *)dict;
/**
* 微博配图地址。多图时返回多图链接。无配图返回“[]”
*/
@property (nonatomic,strong) NSArray *pic_urls;
@end
//我们最初的做法就是statusWithDict,通过将字典中的字段取出来,然后,给模型中的字段赋值。但是出现的情况就是字段太多,我们不可能用这种低效率的方法来处理,这个时候,我们想起用KVC,但是使用KVC出现的情况就是,字典中的属性必须和模型中的属性一一对应,否则会挂。所以KVC这种情况也不能使用。
+ (instancetype)statusWithDict:(NSDictionary *)dict
{
IWStatus *status = [[IWStatus alloc] init];
// status.text = dict[@"text"];
// status.idstr = dict[@"idstr"];
// 利用KVC将字典转换为模型, 模型中的属性必须和字典中的属性一一对应, 否则会挂
[status setValuesForKeysWithDictionary:dict];
return status;
}
==========================================================
现在做法如下:
NSMutableArray *models = [NSMutableArray arrayWithCapacity:newStatus.count];
// 取出新浪返回的所有的微博数据
NSArray *newStatus = responseObject[@"statuses"];
//将数组中的字典循环遍历取出
for (NSDictionary *dict in newStatus)
{
// 将字典转换为模型
注意:objectWithKeyValues是第三方框架(MJExtention)的一个方法
IWStatus *status= [IWStatus objectWithKeyValues:dict];
// 添加到数组中
[models addObject:status];
}
// 将模型数组赋值给属性
self.statuses = models;
=========================================================
//MJExtention还提供了更简单的方法就是直接通过字典数组来转换为模型数组
self.statuses = [IWStatus objectArrayWithKeyValuesArray:newStatus];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 这时,我们从数组中取出的时对应行的微博模型,而不是对应的微博的字典。
// 1.取出对应行的微博模型
IWStatus *status = self.statuses[indexPath.row];
// 2.取出对应行的用户模型
IWUser *user = status.user;
// 3.设置需要显示的数据
cell.detailTextLabel.text = status.text;
cell.textLabel.text = user.name;
NSURL *iconUrl = [NSURL URLWithString:user.profile_image_url];
[cell.imageView sd_setImageWithURL:iconUrl placeholderImage:[UIImage imageWithName:@"timeline_image_placeholder"]];
return cell;
}