好友列表,嵌套模型,自定义头部View代理

本文介绍了一个iOS应用中QQ好友列表的实现方式,包括如何解析数据文件、创建模型类及UITableView的自定义显示。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//
//  ViewController.m
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "ViewController.h"
#import "CZFriend.h"
#import "CZFriendGroup.h"
#import "CZFriendCell.h"
#import "CZFriendHeaderView.h"

@interface ViewController ()<CZFriendHeaderViewDelegate>
//所有模型数据
@property(nonatomic,strong) NSArray *friendGroups;
@end

@implementation ViewController

//懒加载
- (NSArray *)friendGroups
{
    if (_friendGroups==nil) {
        _friendGroups=[CZFriendGroup friendGroups];
    }
    return  _friendGroups;
}

- (BOOL)prefersStatusBarHidden
{
    return  YES;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
}

#pragma mark UITableViewDelegate的数据源方法
//确定组的数量
- (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.friendGroups.count;
}

//确定组中行的数量
- (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    //取出组模型
    CZFriendGroup *fg=self.friendGroups[section];
    //返回当前组中好友数
    return fg.isExpand?fg.friends.count:0;
}
//创建每一行显示的cell
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CZFriendCell *cell=[CZFriendCell friendCell:tableView];
    //取出组模型
    CZFriendGroup *fg=self.friendGroups[indexPath.section];
    //取出这个组中的好友模型
    CZFriend *myFriend=fg.friends[indexPath.row];
    //赋值cell模型
    cell.myFriend=myFriend;
    
    return  cell;
}
//titleForHeaderInSection是为每一个组指定一个头部的字符串值
//- (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
//{
//    //tableHeaderView是用来指定整个UITableView的唯一的顶部view和底部view
//    self.tableView.tableHeaderView=nil;
//}

//viewForHeaderInSection是为每一个组指定一个头部的view
- (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    CZFriendHeaderView *hView=[CZFriendHeaderView friendHeaderView:tableView];
    //指定代理
    hView.delegate=self;
    hView.tag=section;
    //取出组模型
    CZFriendGroup *fg=self.friendGroups[section];
    //为头部view赋值
    hView.friendGroup=fg;
    return hView;
}


- (void)FriendHeaderViewButtonDidClick:(CZFriendHeaderView *)headerView
{
    //reloadData会刷新数据源显示 ,会将三个数据源方法重新调用
    //[self.tableView reloadData];
    //我们只需要刷新当前所点击的这一组
    //NSIndexSet *set=[NSIndexSet indexSetWithIndex:headerView.tag];
    NSIndexSet *set=[NSIndexSet indexSetWithIndex:[self.friendGroups indexOfObject:headerView.friendGroup ]];
    [self.tableView reloadSections:set withRowAnimation:UITableViewRowAnimationAutomatic];
}

@end


<pre name="code" class="objc">#import <Foundation/Foundation.h>

@interface CZFriend : NSObject
//图像
@property (nonatomic,copy) NSString *icon;
//昵称
@property (nonatomic,copy) NSString *name;
//说说
@property (nonatomic,copy) NSString *intro;
//是否vip
@property (nonatomic,assign,getter=isVip) BOOL vip;
//类方法,获取模型对象
+ (instancetype) friendWithDic:(NSDictionary *)dic;
//实例方法,获取模型对象
- (instancetype) initWithDic:(NSDictionary *)dic;
//通过字典数组,返回模型数组
+ (NSArray *)friends :(NSArray *)sourceArr;
@end




<pre name="code" class="objc">//
//  CZFriend.m
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "CZFriend.h"

@implementation CZFriend
//类方法,获取Friend模型对象
+ (instancetype) friendWithDic:(NSDictionary *)dic
{
    return  [[self alloc] initWithDic:dic];
}
//实例方法,获取Friend模型对象
- (instancetype) initWithDic:(NSDictionary *)dic
{
    if(self=[super init])
    {
        [self setValuesForKeysWithDictionary:dic];
    }
    return  self;
}
//将好友字典数组转换为好友模型数组
+ (NSArray *)friends :(NSArray *)sourceArr
{
    NSMutableArray *desArr=[NSMutableArray array];
    for (NSDictionary *dic in sourceArr) {
        //将字典转模型
        CZFriend *f=[CZFriend friendWithDic:dic];
        [desArr addObject:f];
    }
    return  desArr;
}

@end




<pre name="code" class="objc">//
//  CZFriendGroup.h
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface CZFriendGroup : NSObject
//组名
@property (nonatomic,copy) NSString *name;
//在线人数
@property (nonatomic,assign) int online;
//该组好友数组
@property (nonatomic,strong) NSArray *friends;
//类方法,获取好友组模型数据
+ (instancetype) friendGroupWithDic:(NSDictionary *)dic;
//实例方法,获取好友组模型数据
- (instancetype) initWithDic:(NSDictionary *)dic;
//返回所有组模型数据
+ (NSArray *)friendGroups;

//标记是否展开,一开始都是合并
@property (nonatomic,assign) BOOL isExpand;
@end




<pre name="code" class="objc">//
//  CZFriendGroup.m
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "CZFriendGroup.h"
#import "CZFriend.h"

@implementation CZFriendGroup
//类方法返回组模型数据
+ (instancetype) friendGroupWithDic:(NSDictionary *)dic
{
    return  [[CZFriendGroup alloc] initWithDic:dic];
}
//实例方法返回组模型数据
- (instancetype) initWithDic:(NSDictionary *)dic
{
    if(self=[super init])
    {
        [self setValuesForKeysWithDictionary:dic];
//        self.friends=dic[@"friends"];
//        self.name=dic[@"name"];
//        self.online=dic[@"online"];
    }
    return  self;
}
//返回好友组模型数组
+ (NSArray *)friendGroups
{
    NSArray *souArr=[NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"friends.plist" ofType:nil]];
    NSMutableArray *desArr=[[NSMutableArray alloc] init];
    for (NSDictionary *dic in souArr) {
        CZFriendGroup *group=[CZFriendGroup friendGroupWithDic:dic];
        //这里面的friends是字典数组,而不是模型数组,所以需要再将字典转换为模型
        group.friends=[CZFriend friends:group.friends];
        [desArr addObject:group];
    }
    return  desArr;
}

@end




<pre name="code" class="objc">//
//  CZFriendCell.h
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>
@class CZFriend;

@interface CZFriendCell : UITableViewCell

+ (instancetype) friendCell:(UITableView *)tableView;

@property (nonatomic,strong) CZFriend *myFriend;

@end




<pre name="code" class="objc">//
//  CZFriendCell.m
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "CZFriendCell.h"
#import "CZFriend.h"

@implementation CZFriendCell

//如果是结构相同,数据不同,但是系统自带的cell不能满足需要的时候,一般可以使用xib|动态单元格
//2.如果使用代码创建自定义cell,一般需要做initWithStyle方法的重写
+ (instancetype)friendCell:(UITableView *)tableView
{
    NSString *ID=@"friend";
    CZFriendCell *cell=[tableView dequeueReusableCellWithIdentifier:ID];
    if (cell==nil) {
        NSLog(@"我创建了cell");
        cell=[[CZFriendCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
    }
    else
    {
         NSLog(@"我重用了cell");
    }
    return  cell;
}

- (void)setMyFriend:(CZFriend *)myFriend
{
    _myFriend=myFriend;
    
    self.imageView.image=[UIImage imageNamed:myFriend.icon];
    self.textLabel.text=myFriend.name;
    self.detailTextLabel.text=myFriend.intro;
    if (myFriend.isVip) {
        self.textLabel.textColor=[UIColor redColor];
    }
    else
    {
        self.textLabel.textColor=[UIColor blackColor];
    }
}

@end




<pre name="code" class="objc">//
//  CZFriendHeaderView.h
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import <UIKit/UIKit.h>
@class  CZFriendGroup;
@class CZFriendHeaderView;

@protocol CZFriendHeaderViewDelegate <NSObject>

@optional
- (void)FriendHeaderViewButtonDidClick:(CZFriendHeaderView *)headerView;

@end

@interface CZFriendHeaderView : UITableViewHeaderFooterView

+ (instancetype) friendHeaderView:(UITableView *) tableView;

@property (nonatomic,strong) CZFriendGroup *friendGroup;

//定义代理属性,能够遵守并实现我代理方法的就可以成为我的代理
@property (nonatomic,weak) id<CZFriendHeaderViewDelegate> delegate;

@end




<pre name="code" class="objc">//
//  CZFriendHeaderView.m
//  02QQ好友列表
//
//  Created by Itcast.GuangZhou on 15/9/25.
//  Copyright (c) 2015年 itcast. All rights reserved.
//

#import "CZFriendHeaderView.h"
#import "CZFriendGroup.h"

@interface CZFriendHeaderView ()
@property (nonatomic,weak) UIButton *btn;
@property (nonatomic,weak) UILabel *numberLabel;
@end

@implementation CZFriendHeaderView

//返回当前自定义的每一个组的头部view
+ (instancetype)friendHeaderView:(UITableView *)tableView
{
    NSString *ID=@"headerView";
    CZFriendHeaderView *headerView=[tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];
    if (headerView==nil) {
        NSLog(@"headerView 重新创建了");
        //父类这个方法创建一个空的headerView,我们需要对这个方法进行重写
        headerView=[[CZFriendHeaderView alloc] initWithReuseIdentifier:ID];
    }
    else
    {
        NSLog(@"headerView 重用了");
    }
    return headerView;
}

//在init方法里面只是添加子控件,而不去设置frame和数据
- (instancetype)initWithReuseIdentifier:(NSString *)reuseIdentifier
{
    //NSLog(@"%@",NSStringFromCGRect(self.frame));
    self=[super initWithReuseIdentifier:reuseIdentifier];
    if (self) {
        //添加自定义的子控件
        //1.添加按钮
        UIButton *btn=[[UIButton alloc] init];
        //btn.frame=CGRectMake(0, 0, 375, 44);
        //设置小图标
        [btn setImage:[UIImage imageNamed:@"buddy_header_arrow"] forState:UIControlStateNormal];
        //设置背景
        [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg"] forState:UIControlStateNormal];
        [btn setBackgroundImage:[UIImage imageNamed:@"buddy_header_bg_highlighted"] forState:UIControlStateHighlighted];
        [btn setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
        self.btn=btn;
        //设置按钮内容的左对齐
        btn.contentHorizontalAlignment=UIControlContentHorizontalAlignmentLeft;
        //为按钮添加点击事件
        [btn addTarget:self action:@selector(headerBtnDidCilck) forControlEvents:UIControlEventTouchUpInside];
        //设置按钮的旋转是按默认的旋转轴心进行旋转
        self.btn.imageView.contentMode=UIViewContentModeCenter;
//        //设置按钮旋转后,超出原始边界的部分不要截切,要保留
        self.btn.imageView.clipsToBounds=NO;
        //添加创建好的按钮到头部view
        [self addSubview:btn];
        
        //2.添加UILabel
        UILabel *numberLabel=[[UILabel alloc] init];
        //numberLabel.frame=CGRectMake(300, 0, 75, self.frame.size.height);
        //numberLabel.backgroundColor=[UIColor redColor];
        //设置文本右对齐
        numberLabel.textAlignment=NSTextAlignmentRight;
        //设置按钮左间距
        btn.contentEdgeInsets=UIEdgeInsetsMake(0, 10, 0, 0);
        //设置按钮文本与小图标之间的距离
        btn.titleEdgeInsets=UIEdgeInsetsMake(0, 10, 0, 0);
        self.numberLabel=numberLabel;
        [self addSubview:numberLabel];
    }
    return self;
}


- (void)setFriendGroup:(CZFriendGroup *)friendGroup
{
    _friendGroup=friendGroup;
    [self.btn setTitle:friendGroup.name forState:UIControlStateNormal];
    self.numberLabel.text=[NSString stringWithFormat:@"%d/%ld",friendGroup.online,friendGroup.friends.count];
   
}
//将当前控件添加到父容器的时候调用这个方法
- (void) willMoveToSuperview:(UIView *)newSuperview
{
    //重新创建headerView会调用这个Set赋值方法
    if(self.friendGroup.isExpand)
    {
        //将小图标进行旋转
        self.btn.imageView.transform=CGAffineTransformMakeRotation(M_PI_2);
    }
    else
    {
        self.btn.imageView.transform=CGAffineTransformMakeRotation(0);
    }
}

//将一个控件 添加到父容器的时候,会自动调用这个方法设置它的子控件的frame
- (void)layoutSubviews
{
    //NSLog(@"frame:%@",NSStringFromCGRect(self.frame));
    [super layoutSubviews];
    self.btn.frame=CGRectMake(0, 0, self.frame.size.width, self.frame.size.height);
    self.numberLabel.frame=CGRectMake(300, 0, 65, self.frame.size.height);
}


- (void) headerBtnDidCilck
{
    //修改当前 的展开属性
    self.friendGroup.isExpand=!self.friendGroup.isExpand;
    //当有点击操作的时候,就告诉(tell)它的代理进行处理
    if ([self.delegate respondsToSelector:@selector(FriendHeaderViewButtonDidClick:)]) {
        [self.delegate FriendHeaderViewButtonDidClick:self];
    }
}
@end





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值