IOS开发UI进阶之UITableView一

一 UITableView

  • 什么是UITableView
    • 在iOS中要实现展示列表数据,最常用的做法就是使用UITableView
    • UITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳
  • UITableView的两种样式(Table View→Style)
    • UITableViewStylePlain(普通样式)
    • UITableViewStyleGrouped(分组样式)
  • 如何展示数据
    • UITableView需要一个数据源(dataSource)来显示数据
    • UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等
    • 凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源
  • tableView和数据源
    这里写图片描述

二 UITableView基本用法

  • 设置数据源
  self.tableView.dataSource = self;
  • 数据源遵守数据源协议

@interface ViewController () <UITableViewDataSource>
  • 实现数据源方法
// 1.返回有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
// 2.返回每组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.wines.count;
}
// 3.返回每一行的内容(UITableViewCell类型)
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

4.tablView的常见属性

//1. 修改tableView的行高
    self.tableView.rowHeight = 100;

    // 2.组头组尾的高
    self.tableView.sectionHeaderHeight = 55;
    self.tableView.sectionFooterHeight = 22;

    // 3.设置整个tablView的头部/尾部视图
    self.tableView.tableHeaderView = [[UISwitch alloc] init];
    self.tableView.tableFooterView = [UIButton buttonWithType:UIButtonTypeInfoDark];

    // 4.设置我们分割线颜色(clearColor相当于取消系统分割线)
    //self.tableView.separatorColor = [UIColor clearColor];

    // 5.设置分割线样式
    self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone;

    // 设置索引条内部文字颜色为不纯洁颜色
    self.tableView.sectionIndexColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:1];
    // 设置索引条背景颜色为纯洁颜色
    self.tableView.sectionIndexBackgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:1];
  • tableViewCell 的常见属性
// 设置cell右边样式
    cell.accessoryType;
    cell.accessoryView;
// cell.accessoryView优先级 > accessoryType
    // selectedBackgroundView设置选中背景优先级是比selectionStyle高
    UIView *bg = [[UIView alloc] init];
    bg.backgroundColor = [UIColor purpleColor];
//    cell.selectedBackgroundView = bg;
//    //UITableViewCellSelectionStyleBlue 在iOS7之后和Gray效果相同
//    cell.selectionStyle = UITableViewCellSelectionStyleBlue;

    // backgroundView它的优先级比backgroundColor高,并且这俩是并存
    cell.backgroundView = bg;
    cell.backgroundColor = [UIColor yellowColor];

    cell.contentView;
  • tableView常用代理方法
// 当选中index行cell时候会调用
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

// 当取消选中cell时候调用
- (void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath

// 返回对应行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

// 返回对应组的组头高度
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section

// 返回对应组头试图
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section

三 展示多组数据

  • 字典样式
@interface ViewController () <UITableViewDataSource>
@property (nonatomic, strong) NSArray *carGroups; /**< carGroup模型数组 */
@end
- (NSArray *)carGroups
{
    if (!_carGroups) {      
 NSArray *cars = @[[XMGCar carWithName:@"奔驰" Logo:@"m_2_100"],
                   [XMGCar carWithName:@"宝马" Logo:@"m_3_100"],
                          ];
 XMGCarGroup *carGroup0 = [XMGCarGroup carGroupWithHeader:@"德系品牌" Footer:@"的新品牌高大上的footer" Cars:cars];

NSArray *cars1 = @[
[XMGCar carWithName:@"法拉利" Logo:@"m_91_100"],
[XMGCar carWithName:@"兰博基尼" Logo:@"m_86_100"],
[XMGCar carWithName:@"玛莎拉蒂" Logo:@"m_93_100"],
                          ];
XMGCarGroup *carGroup1 = [XMGCarGroup carGroupWithHeader:@"意大利系品牌" Footer:@"意大利的新品牌高大上的footer" Cars:cars1];

NSArray *cars2 = @[[XMGCar carWithName:@"比亚迪" Logo:@"m_15_100"],
                        ];
XMGCarGroup *carGroup2 = [XMGCarGroup carGroupWithHeader:@"天系品牌" Footer:@"china的新品牌高大上的footer" Cars:cars2];

        _carGroups = @[carGroup0, carGroup1, carGroup2];
    }
    return _carGroups;
}
  • 字典转模型方法(XMGCarGroup)
+ (instancetype)carGroupWithDict:(NSDictionary *)dict
{
    XMGCarGroup *carGroup = [[XMGCarGroup alloc] init];

    carGroup.header = dict[@"header"];
    carGroup.footer = dict[@"footer"];

    // 1.拿到字典数组
    NSArray *dictCars = dict[@"cars"];
    // 2.字典数组-> 模型数组
    NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:dictCars.count];
    for (NSDictionary *dictCar in dictCars) {
        XMGCar *car = [XMGCar carWithDict:dictCar];
        [arrayM addObject:car];
    }
    // 要求cars是car模型数组,而不是字典数组
    carGroup.cars = [arrayM copy];

    return carGroup;
}
  • 组头组尾设置
// 返回组头文字:note:(如果是英文他会自动变成大写)
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    XMGCarGroup *carGroup = self.carGroups[section];
    return carGroup.header;
}

// 返回组尾文字
- (NSString *)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    XMGCarGroup *carGroup = self.carGroups[section];
    return carGroup.footer;
}
  • 复杂plist解析→数组转模型
// 懒加载
#warning 当不展示数据时,先看!_carGroups的!是否写了,再看plist是否敲对
- (NSArray *)carGroups
{
    if (!_carGroups) {
        // 1.获取我们的plist文件路径
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cars" ofType:@"plist"];


        // 2.获取dict数组
        NSArray *dictCarGroups = [NSArray arrayWithContentsOfFile:filePath];

        // 3.将dict数组->模型数组
        NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:dictCarGroups.count];
        for (NSDictionary *dict in dictCarGroups) {
            XMGCarGroup *carGroup = [XMGCarGroup carGroupWithDict:dict];
            [arrayM addObject:carGroup];
        }
        // 4.赋值
        _carGroups = [arrayM copy];
        }
    return _carGroups;
}
  • 实现tableView样式
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return self.carGroups.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    XMGCarGroup *carGroup = self.carGroups[section];
    return carGroup.cars.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 1.创建cell
    UITableViewCell *cell = [[UITableViewCell alloc] init];

    // 2.设置cell右边样式
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    // 3.设置cell内部的数据
    XMGCarGroup *carGroup = self.carGroups[indexPath.section];
    XMGCar *car = carGroup.cars[indexPath.row];

    cell.textLabel.text = car.name;
    cell.imageView.image = [UIImage imageNamed:car.icon];

    // 4.返回
    return cell;
}

三 展示单组数据

// 懒加载
- (NSArray *)wines
{
    if (nil == _wines) {
        // 1.
        NSString *filePath = [[NSBundle mainBundle] pathForResource:@"wine.plist" ofType:nil];
        // 2.加载字典数组
        NSArray *dictWines = [NSArray arrayWithContentsOfFile:filePath];
        // 3.数组转字典
        NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:dictWines.count];
        for (NSDictionary *dict in dictWines) {
            XMGWine *wine = [XMGWine wineWithDict:dict];
            [arrayM addObject:wine];
        }
        _wines = [arrayM copy];
    }
    return _wines;
}
  • Cell简介

    • UITableView的每一行都是一个UITableViewCell,
      • 通过dataSource的tableView:cellForRowAtIndexPath:方法来初始化每一行
    • UITableViewCell内部有个默认的子视图:contentView,
      • contentView是UITableViewCell所显示内容的父视图,可显示一些辅助指示视图
    • 辅助指示视图可以通过设置UITableViewCell的accessoryType来显示
      • 默认是UITableViewCellAccessoryNone(不显示辅助指示视图),其他值如下:
        这里写图片描述
  • UITableViewCell的contentView

    • contentView下默认有3个子视图
      • 2个是UILabel(通过UITableViewCell的textLabel和detailTextLabel属性访问)
      • 第3个是UIImageView(通过UITableViewCell的imageView属性访问)
    • UITableViewCellStyle属性
      • 作用决定这些子视图在contentView中的位置
        这里写图片描述

四 性能优化

  • 系统可以做到cell用到几个创建几个,存在问题就是重复创建cell
    • cell样式一样,地址不一样
  • 性能优化(缓存池)

    • 通过一个标识去缓存池中找可循环利用的cell
    • 如果缓存池中找不到可循环利用的cell,创建一个新的cell,给cell贴上标识
    • 给cell设置新的数据
  • cell的循环利用

    • 传统的写法

      /**
      *  每当有一个cell要进入视野范围内,就会调用一次
      */
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
      static NSString *ID = @"wine";
      
      // 1.先去缓存池中查找可循环利用的cell
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
      
      // 2.如果缓存池中没有可循环利用的cell
      if (!cell) {
          cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
      }
      
      // 3.设置数据
      cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row];
      
      return cell;
      }
    • 新的写法(注册cell)

      NSString *ID = @"wine";
      
      - (void)viewDidLoad {
      [super viewDidLoad];
      
      // 注册某个重用标识 对应的 Cell类型
      [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:ID];
      }
      
      - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
      {
      // 1.先去缓存池中查找可循环利用的cell
      UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
      
      // 2.设置数据
      cell.textLabel.text = [NSString stringWithFormat:@"%zd行的数据", indexPath.row];
      
      return cell;
      }

五 索引条

  • 做法一:

    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
    {
    return [self.carGroups valueForKeyPath:@"title"];
    }
  • 做法二:

    - (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
    {
    NSMutableArray *arrayM = [NSMutableArray array];
    for (XMGCarGroup *carGroup in self.carGroups) {
    [arrayM addObject:carGroup.title];
    } 
    return arrayM;
    }
    
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值