UI基础-UITableViewHeaderFooterView组标题数据不加载,好友列表只能点击不能打开

一、案例描述:案例类似于QQ好友列表的展开和关闭,每次点击组标题后,展开列表并刷新被点击的一组



二、BUG描述:点击某组标题后,列表无法展开且列表上控件不显示,但该组数据已刷新,断点调试数据已传入,按钮点击事件已执行。

三、代码如下:

1、控制器代码:

//
//  ViewController.m
//
//  Created by craneteng on 16/1/3.
//  Copyright © 2016年 craneteng. All rights reserved.
//
#import "ViewController.h"
#import "HMdata.h"
#import "HMGroupHeaderView.h"
@interface ViewController ()<HMGroupHeaderViewDelegate>
@property(nonatomic,strong)NSArray *data;
@end

@implementation ViewController

#pragma mark - 实现数据源方法
-(NSInteger )numberOfSectionsInTableView:(UITableView *)tableView{
    return self.data.count;
}
-(NSInteger )tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    // 1. 获取组模型
    HMdata *modle = self.data[section];
    if (modle.isVisible) {
        //点击后打开图片
        return 1;
    } else {
        return 0;
    }
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

   NSString *ID = @"cell_id";
   UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    //创建cell
    if (cell == nil) {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
    }
    //赋值
    cell.imageView.image = [UIImage imageNamed:@"泡妞宝典"];
    cell.textLabel.text = @"程序名媛";
    
    //返回cell
    return cell;
}

#pragma mark - 实现组标题的代理方法,自定义每组的header
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{
    //获取模型数据
    HMdata *modle = self.data[section];
    //创建一个自定义headerView,并传入模型数据
    HMGroupHeaderView *headerView = [[HMGroupHeaderView alloc]groupHeaderViewWithTableView:tableView andModle:modle];
    //设置代理用于刷新对应组数据
    headerView.delegate = self;
    // 把当前是第几组, 记录到header view中
    headerView.tag = section;
    // 4. 返回header view
    return headerView;
}

#pragma mark - 实现代理方法刷新数据
-(void)didClickHeaderViewButton:(HMGroupHeaderView *)headerView{
    // 局部刷新 (只刷新某组)
    NSIndexSet *idx_set = [NSIndexSet indexSetWithIndex:headerView.tag];
    [self.tableView reloadSections:idx_set withRowAnimation:UITableViewRowAnimationRight];
}

#pragma mark - 隐藏状态栏
- (BOOL)prefersStatusBarHidden {
    return YES;
}

#pragma mark - 加载数据
-(NSArray *)data{
    if (_data == nil) {
        NSString *path = [[NSBundle mainBundle]pathForResource:@"Data.plist" ofType:nil];
        NSArray *dicM = [NSArray arrayWithContentsOfFile:path];
        NSMutableArray *arrayM = [NSMutableArray array];
        for (NSDictionary *dict in dicM) {
            HMdata *modle = [HMdata dataWithdict:dict];
            [arrayM addObject:modle];
        }
        _data = arrayM;
    }
    return _data;
}

- (void)viewDidLoad {
    self.tableView.rowHeight = 90;
   self.tableView.sectionHeaderHeight = 44;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

2、自定义headerView代码:

#import <UIKit/UIKit.h>
@class HMdata,HMGroupHeaderView;
//创建一个代理
@protocol HMGroupHeaderViewDelegate <NSObject>
-(void)didClickHeaderViewButton:(HMGroupHeaderView *)headerView ;
@end

@interface HMGroupHeaderView : UITableViewHeaderFooterView

@property (weak,nonatomic)id<HMGroupHeaderViewDelegate> delegate;

-(instancetype )groupHeaderViewWithTableView:(UITableView *)tableView andModle:(HMdata *)modle;

@end

#import "HMGroupHeaderView.h"
#import "HMdata.h"
@interface HMGroupHeaderView ()
@property (nonatomic, weak) UIButton *button;
@property (nonatomic, weak) UILabel *label;
@property(nonatomic,copy) HMdata *data;
@end

@implementation HMGroupHeaderView

-(instancetype )groupHeaderViewWithTableView:(UITableView *)tableView andModle:(HMdata *)modle{
    _data = modle;
    //创建组标题
    static NSString *ID = @"group_id";
    HMGroupHeaderView *headerView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];
    if (headerView == nil) {
        headerView = [[HMGroupHeaderView alloc] initWithReuseIdentifier:ID];
    }
    // 把数据设置给子控件
    // 设置按钮上显示的文字
    [self.button setImage:[UIImage imageNamed:modle.imageName] forState:UIControlStateNormal];
    // 设置label上显示的文字
    self.label.text = modle.titileName;
    return headerView;
}

//重写自定义组标题
-(instancetype )initWithReuseIdentifier:reuseIdentifier{
    if (self = [super initWithReuseIdentifier:reuseIdentifier]){
        UIButton *button = [[UIButton alloc]init];
        //设置按钮图片
        // 设置按钮中整个内容左对齐
        button.contentHorizontalAlignment = UIControlContentHorizontalAlignmentLeft;
        // 设置按钮的文字是黑色
        [button setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
//         为按钮注册一个单击事件
        [button addTarget:self action:@selector(didClickHeaderButton:) forControlEvents:UIControlEventTouchUpInside];
        [self.contentView addSubview:button];
        self.button = button;
        
        // label
        UILabel *label = [[UILabel alloc] init];
        
        // 设置文字右对齐
        label.textAlignment = NSTextAlignmentRight;
//        label.text = self.data.titileName;
//        NSLog(@"%@",self.modle.titileName);
        [self.contentView addSubview:label];
        self.label = label;
        }
    return self;
    }

- (void)layoutSubviews {
    [super layoutSubviews];
    // 设置按钮和label的frame值
    // 1. button
    self.button.frame = self.bounds;
    // 2. label
    CGFloat margin = 20;
    CGFloat labelH = self.bounds.size.height;
    CGFloat labelW = 120;
    CGFloat labelY = 0;
    CGFloat labelX = self.bounds.size.width - labelW - margin;
    
    self.label.frame = CGRectMake(labelX, labelY, labelW, labelH);
}

// 点击了"标题按钮"
- (void)didClickHeaderButton:(UIButton *)sender {
    
    // 设置当前组的"显示状态"
    _data.visible = !_data.visible;
    
    // 调用代理对象的方法
    if ([self.delegate respondsToSelector:@selector(didClickHeaderViewButton:)]) {
        [self.delegate didClickHeaderViewButton:self];
    }

}

@end

四、BUG解决:

1、常见思路是在控制器当中用类方法让自定义headerView创建组标题,各种数据通过重写模型的set方法来传入,代码如下:

控制器代码:

    //创建一个自定义headerView,并传入模型数据
    HMGroupHeaderView *headerView1 = [HMGroupHeaderView groupHeaderViewWithTableView:tableView];
//    传入模型数据
    headerView1.data = modle;

自定义headerView代码:

创建:

+(instancetype )groupHeaderViewWithTableView:(UITableView *)tableView{
//    NSLog(@"%@",modle.titileName);
//    NSLog(@"%@",_modle.titileName);
    //创建组标题
    static NSString *ID = @"group_id";
    HMGroupHeaderView *headerView2 = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];
    if (headerView2 == nil) {
        headerView2 = [[HMGroupHeaderView alloc]initWithReuseIdentifier:ID];
    }
    return headerView2;
}

设置数据:

- (void)setData:(HMdata *)data{
    
    _data = data;
    
    // 把数据设置给子控件
    // 设置按钮上显示的文字
    [self.button setImage:[UIImage imageNamed:data.imageName] forState:UIControlStateNormal];
    
    // 设置label上显示的文字
    self.label.text = data.titileName;
}

2、如果不通过set方法给自定义headerView传入数据,依然想通过对象方法带模型参数直接赋值,修改y以下代码:

    if (headerView == nil) {
        headerView = [[HMGroupHeaderView alloc] initWithReuseIdentifier:ID];
    }

这句中,通过 [HMGroupHeaderView alloc] 又重新创建了一个自定义headerView,与控制器中这句

HMGroupHeaderView *headerView = [[HMGroupHeaderView alloc]groupHeaderViewWithTableView:tableView andModle:modle];
重复创建了两个对象,导致数据赋值后没有返回到控制器,要保持自定义headerView类和控制器中创建的是一个对象, 自定义headerView类中修改代码如下:

    if (headerView == nil) {
        headerView = [self initWithReuseIdentifier:ID];
    }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值