1. 最近好累
2. 很想念一个人
3. 开始整理
</pre>qq好友列表 数据模型从plist文件中读取。plist文件较为复杂<pre>
</pre><img src="https://img-blog.csdn.net/20150817210704933?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />数组中 一个有12个字典 ,即分组,每个分组有一个朋友数组 又由好多字典组成。 所以我们确定,分组是一个数据模型类,而朋友也是一个数据模型类<pre name="code" class="objc">1.分组数据模型类
/**类方法用来创建model对象*/
+ (id)groupModelWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
/**实例方法用来创建model对象*/
- (id)initWithDict:(NSDictionary *)dict {
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
NSMutableArray *friends = [NSMutableArray array];
// 这个之前friend数组中存放的是字典,而不是数据模型
for (NSDictionary *dict in self.friends) {
// 将friend数组每个元素封装(更新)为数据模型
YXFriendModel *friendModel = [YXFriendModel friendModelWithDict:dict];
[friends addObject:friendModel];
}
[self setValue:friends forKey:@"friends"];
// _friends = objs;
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:@"title:%@,friends:%@,online:%@", _title,_friends,_online];
}
我们需要在将分组字典转模型的时候,将朋友的内容也转为模型。
因为我们需要通过分组模型类得到朋友模型类的内容。所以需要这样设计。
这就是所谓的模型中存放模型。
/**类方法用来创建friend - model对象*/
+ (id)friendModelWithDict:(NSDictionary *)dict {
return [[self alloc] initWithDict:dict];
}
/**实例方法用来创建friend - model对象*/
- (id)initWithDict:(NSDictionary *)dict {
if (self = [super init]) {
[self setValuesForKeysWithDictionary:dict];
}
return self;
}
- (NSString *)description
{
return [NSString stringWithFormat:@"icon:%@,message:%@,name:%@", _icon,_message,_name];
}
我们需要将分组的视图 封装。
即分组头视图
#import <UIKit/UIKit.h>
#import "YXGroupModel.h"
@class YXGroupHeaderView;
typedef void(^GroupHeaderViewArrowBtnTouchBlock)(YXGroupHeaderView *groupHeaderView,UIButton *button,BOOL isExpend);
@interface YXGroupHeaderView : UITableViewHeaderFooterView // 需要继承才可以设置标签
@property (nonatomic,strong) YXGroupModel *groupModel;
@property (nonatomic,weak) UIButton *button;
@property (nonatomic,copy) GroupHeaderViewArrowBtnTouchBlock myBlock;
+ (id)groupHeaderViewWithTableView:(UITableView *)tableView;
@end
#import "YXGroupHeaderView.h"
@interface YXGroupHeaderView ()
/**用来记录是否展开*/
@property (nonatomic,assign) BOOL isExpend;
@end
@implementation YXGroupHeaderView
+ (id)groupHeaderViewWithTableView:(UITableView *)tableView {
// 1. 缓存池中找是否有可重用的headerView 或者是footerView
// 2. 如果没有那么自己创建一个出来
YXGroupHeaderView *groupHeaderView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:@"YXGroupHeaderView"];
if (groupHeaderView == nil) {
groupHeaderView = [[YXGroupHeaderView alloc] initWithReuseIdentifier:@"YXGroupHeaderView"];
}
return groupHeaderView;
}
- (void)setGroupModel:(YXGroupModel *)groupModel {
_groupModel = groupModel;
// 用groupModel中的isExpend属性来记录 因为分组头视图会被销毁 isExpend会更新,所以需要记录下之前的isExpend
// 即不断给分组头视图 以 新的记录标示 (用当前的分组视图的状态 展开或者关闭来标示)
self.isExpend = groupModel.isExpend;
self.button.imageView.transform = self.isExpend ? CGAffineTransformMakeRotation(M_PI/2) : CGAffineTransformIdentity;
// 更新UI数据
[self.button setTitle:[groupModel valueForKey:@"title"] forState:UIControlStateNormal];
}
#pragma mark - 逻辑辅助功能
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[self addSubview:button];
[button addTarget:self action:@selector(btnTouch:) forControlEvents:UIControlEventTouchUpInside];
[button setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
[button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
button.titleLabel.font = [UIFont systemFontOfSize:13];
// 调整位置
// 1. 先去最左边
button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
// 2. 然后调整 以最左边为参照
button.contentEdgeInsets = UIEdgeInsetsMake(0, 20, 0, 0);
button.titleEdgeInsets = UIEdgeInsetsMake(0, 15, 0, 0);
//是否设置边框以及是否可见
[[button layer] setMasksToBounds:YES];
//设置边框圆角的弧度
[[button layer] setCornerRadius:5.0];
//设置边框线的宽
[[button layer] setBorderWidth:0.5];
_button = button;
}
return self;
}
- (void)willMoveToSuperview:(UIView *)newSuperview {
self.contentView.backgroundColor = [UIColor lightGrayColor];
self.button.frame = self.bounds;
}
#pragma mark - 按钮点击事件
- (void)btnTouch:(UIButton *)button {
_isExpend = !_isExpend;
button.selected = _isExpend;
if (self.myBlock) {
self.myBlock(self,button,button.selected);
}
}
封装cell
#import "YXFriendCell.h"
@implementation YXFriendCell
+ (id)friendCellWithTableView:(UITableView *)tableView {
NSString *identifier = NSStringFromClass([self class]);
YXFriendCell *cell = [tableView dequeueReusableCellWithIdentifier:@"identifier"];
if (cell == nil) {
cell = [[YXFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:identifier];
}
return cell;
}
#pragma mark - 辅助逻辑功能
/**外部接口,用来更新UI数据*/
- (void)setFriendModel:(YXFriendModel *)friendModel {
_friendModel = friendModel;
self.imageView.image = [UIImage imageNamed:friendModel.icon];
self.textLabel.text = friendModel.name;
self.detailTextLabel.text = friendModel.message;
}
@end
难点在于,我们需要判断是显示0个人还是朋友列表 折叠效果 ,每一次点击分组视图,我们都会处理事件。表视图刷新数据。
分组视图会被销毁,所以它的标记每次都会被初始化为NO,所以我们需要在每一个分组的model上设置一个标记,标记是否展开或者关闭。 当每次给头视图数据时,将此标记赋给表视图的标记。因为每个分组的model不会销毁,所以它记录的是否展开是正确的。
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
YXGroupModel *groupModel = [self.groups objectAtIndex:section];
if (groupModel.isExpend) { // 展开
return [[groupModel friends] count];
} else
return 0;
}
#pragma mark - UITableView 代理方法
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
YXGroupModel *groupModel = [self.groups objectAtIndex:section];
YXGroupHeaderView *groupHeaderView = [YXGroupHeaderView groupHeaderViewWithTableView:tableView];
groupHeaderView.groupModel = groupModel;
[groupHeaderView setMyBlock:^(YXGroupHeaderView *groupHeaderView,UIButton *button,BOOL isExpend){
// 点击事件响应后,分组头视图传过来一个是否展开的标记
groupModel.isExpend = isExpend;
// 刷新TableView
[tableView reloadData];
}];
return groupHeaderView;
}