单组表格UITableView

network | | 访问(44)
#import "ViewController.h"
#import "Hero.h"

@interface ViewController () <UITableViewDataSource, UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSArray *heros;
@end

@implementation ViewController

- (NSArray *)heros
{
    if (_heros == nil) _heros = [Hero heros];
    return _heros;
}

/**
 UITableViewStylePlain,     // 平板的格式
 UITableViewStyleGrouped    // 分组的格式
 */
- (UITableView *)tableView
{
    if (_tableView == nil) {
        // 表格控件在创建时必须指定样式,只能使用以下实例化方法
        _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
        
        _tableView.dataSource = self;
        _tableView.delegate = self;
        
        [self.view addSubview:_tableView];
    }
    return _tableView;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
    [self tableView];
    
    // 设置行高
    self.tableView.rowHeight = 80;
    // 分隔线
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleSingleLine;
    /**
     32位真彩色 ARGB 2^8 * 2^8 * 2^8 * 2^8 = 2^32 = 2^2 * 2^10 * 2^10 * 2^10  = 4G
     2^64 = 16 GG
     
     A = Alpha
     R
     G
     B
     24位真彩色 RGB 2^8 * 2^8 * 2^8 = 2 ^ 24 = 2^4 * 2^10 = 16 * 100万
     R = Red     1个字节  8位 0~255
     G = Green
     B = Blun
     
     # ff ff ff ff
     */
    self.tableView.separatorColor = [UIColor colorWithWhite:0.0 alpha:0.2];
    
    // headView,放在tableView最顶部的视图,通常用来放图片轮播器
    UIView *head = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 130)];
    head.backgroundColor = [UIColor blueColor];
    self.tableView.tableHeaderView = head;
    
    // footerView,通常做上拉刷新
    UIView *foot = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 44)];
    foot.backgroundColor = [UIColor redColor];
    self.tableView.tableFooterView = foot;
}

#pragma mark - 数据源方法
// 每个分组中的数据总数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.heros.count;
}

/**
 UITableViewCellStyleDefault,   默认类型 标题+可选图像
 UITableViewCellStyleValue1,    标题+明细+图像
 UITableViewCellStyleValue2,    不显示图像,标题+明细
 UITableViewCellStyleSubtitle   标题+明细+图像
 */
// 告诉表格每个单元格的明细信息,此方法的调用频率非常高!
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    // 0. 可重用标示符字符串
    // static静态变量,能够保证系统为变量在内存中只分配一次内存空间
    // 静态变量,一旦创建,就不会被释放,只有当应用程序被销毁时,才会释放!
    static NSString *ID = @"Cell";
    // 1. 取缓存池查找可重用的单元格
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    // UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:nil];
    // 2. 如果没有找到
    if (cell == nil) {

        // 创建单元格,并设置cell有共性的属性
        
        // 实例化新的单元格
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
        
        // 设置右边的箭头
        // 1> UITableViewCellAccessoryDisclosureIndicator 箭头,可以"提示"用户,当前行是可以点击的,通常选中行,会跳到新的页面
        // 2> UITableViewCellAccessoryCheckmark 对号,通常提示用户该行数据设置完毕,使用的比较少
        // 3> UITableViewCellAccessoryDetailButton 按钮,通常点击按钮可以做独立的操作,例如alertView
        //   点击按钮并不会选中行
        // 4> UITableViewCellAccessoryDetailDisclosureButton 按钮+箭头,各自操作
        //    cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
    
        // 指定右侧的自定义视图
        /**
        通常accessoryType提供的类型不能满足时,才会使用自定义控件
     
        但是需要自行添加监听方法,通常用在自定义cell,不要写在视图控制器中!!!
     
        自定义控件的事件触发,同样不会影响表格行的选中!
        */
        UISwitch *switcher = [[UISwitch alloc] init];
        // 添加监听方法
        [switcher addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged];
    
        cell.accessoryView = switcher;
        
        // 背景颜色,会影响到未选中表格行的标签背景
        // cell.backgroundColor = [UIColor redColor];
        // 在实际开发中,使用背景视图的情况比较多
        // 背景视图,不需要指定大小,cell会根据自身的尺寸,自动填充调整背景视图的显示
        // UIImage *bgImage = [UIImage imageNamed:@"img_01"];
        // cell.backgroundView = [[UIImageView alloc] initWithImage:bgImage];
        // UIView *bgView = [[UIView alloc] init];
        // bgView.backgroundColor = [UIColor yellowColor];
        // cell.backgroundView = bgView;
        // 没有选中的背景颜色
        // 选中的背景视图
        // UIImage *selectedBGImage = [UIImage imageNamed:@"img_02"];
        // cell.selectedBackgroundView = [[UIImageView alloc] initWithImage:selectedBGImage];
    }

    // 设置单元格内容
    Hero *hero = self.heros[indexPath.row];
    
    // 标题
    cell.textLabel.text = hero.name;
    // 明细信息
    cell.detailTextLabel.text = hero.intro;
    // 图像
    cell.imageView.image = [UIImage imageNamed:hero.icon];

    return cell;
}

- (void)switchChanged:(UISwitch *)sender
{
    NSLog(@"%s %@", __func__, sender);
}

#pragma mark - 代理方法
// accessoryType为按钮时,点击右侧按钮的监听方法
// 此方法不会触发行选中,跟行选中各自独立
// 只是为accessoryType服务,对自定义控件不响应
- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%s %@", __func__, indexPath);
}

// 取消选中某一行,极少用,极容易出错!
// didDeselectRowAtIndexPath
// didSelectRowAtIndexPath
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%s %@", __func__, indexPath);
}

// 选中了某一行,有箭头的
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSLog(@"%s %@", __func__, indexPath);
}

/**
 代理方法的优先级比rowHeight优先级高
 
 应用场景:很多应用程序,每一行的高度是不一样的,例如:新浪微博
 
 表格工作观察的小结
 
 1> 要知道总共有多少数据
 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 
 2> 计算“每一行”的行高
 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
 
 问题:在此方法执行时,cell被实例化了吗?
 方法的作用是什么?
 
 scrollView需要指定contentSize才能够滚动,如果没有实现方法,行高默认是44
 
 需要知道每一行的高度,才能够准确的计算出contentSize
 
 知道每一行的高度后,自然知道每一个屏幕应该显示多少行,表格明细方法的执行次数就知道了
 
 3> 表格明细
 调用屏幕显示所需要的行数,懒加载,只有要显示的表格行,才会被实例化!
 
 小的结论:
 
 *  tableView.rowHeight:效率高,适用于所有的表格行高度一致
 *  代理方法指定行高:  效率差,适合于每一个行的行高不一样,能够让表格更加的灵活
 
 */
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return (indexPath.row % 2) ? 60 : 44;
}

@end
#import "Hero.h"

@implementation Hero

- (instancetype)initWithDict:(NSDictionary *)dict
{
    self = [super init];
    if (self) {
        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}

+ (instancetype)heroWithDict:(NSDictionary *)dict
{
    return [[self alloc] initWithDict:dict];
}

+ (NSArray *)heros
{
    NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"heros.plist" ofType:nil]];
    
    NSMutableArray *arrayM = [NSMutableArray array];
    for (NSDictionary *dict in array) {
        [arrayM addObject:[self heroWithDict:dict]];
    }
    
    return arrayM;
}

@end
#import <Foundation/Foundation.h>

@interface Hero : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon;
@property (nonatomic, copy) NSString *intro;

- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)heroWithDict:(NSDictionary *)dict;

+ (NSArray *)heros;

@end