iOS UI基础学习 Note_dayEight

上了一天的STM32,略疲劳,不过还是更新下blog吧,学校请了外面的培训机构来培训STM32,终于了解到了那些去读培训班的朋友也是很累.本来就自学过的知识再听一遍也是无比枯燥,还好只有6周的课程,为了3个学分,忍了吧.

今天讲一下UITableView,一个继承与UIScrollView的控件,比UIScrollView功能要强大一点点的控件,也是现在一些常见的app中滚动页面里面最常见的控件了吧

那么就进入主题吧,内容不是很多

UITableView

今天通过一个demo来讲解UITableView,是一个汽车选择界面,如图所示
dayEight01
该界面可以滚动,显示汽车的标志和名字(有点像汽车之家选择汽车的那个界面),这个首先在storyboard中拖一个UITableView控件到View中,设置好约束好,更新frame,达到以下图片的效果
dayEight02
dayEight03
因为要传入数据,所以应该设置数据源dataSource,右键UITableView控件,会有一个弹窗出现,选中dataSource然后拖一根线连接到ViewController,将控制器设置为自己的数据源,也可以用代码self.tableView.dataSource = self;
效果是一样的,当然添加了数据源,就得准守数据源协议,所以要在ViewController.m的中的@interface ViewController ()添加 <UITableViewDataSource>
接下来就可以添加一些数据啦,首先我们来分析保持这些数据的plist文件吧,我通过一个图片来说明
dayEight04
图片里面我已经有所标注了,我们先创建一个模型来接受这些数据,在plist文件中要一层一层往下分析,如果遇到有字典,就用一个模型来接收它,再从最低层开始创建cars的类,在.h中创建用于接收icon和name两个字符串的对象,在.h文件中的代码如下

@interface Cars : NSObject

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *icon;

+ (instancetype)carsWithDict:(NSDictionary *)dict;

在.m中的代码如下

@implementation Cars

+ (instancetype)carsWithDict:(NSDictionary *)dict
{
    Cars *car = [[self alloc]init];
    [car setValuesForKeysWithDictionary:dict];
/*
使用KVC方法,将字典里面的键值对赋值给模型的键值对,使用该方法必须是模型和plist文件的键值对一一对应,缺一不可
*/  
    return car;
}
@end

接下来创建一个CarGroups类,.h文件中的代码如下

@interface CarGroups : NSObject
@property (nonatomic, copy) NSString *title;
@property (nonatomic, copy) NSArray *cars;
//接受标题和car数组的对象
+ (instancetype)carGroupsWithDict:(NSDictionary *)dict;
//提供快速构造方法

在.m的文件中代码如下

#import "CarGroups.h"
#import "Cars.h"
@implementation CarGroups

+ (instancetype)carGroupsWithDict:(NSDictionary *)dict
{
    CarGroups *groups = [[self alloc]init];
    groups.title = dict[@"title"];
//把plist文件中的标题赋值给模型的title
    NSMutableArray *tempDict = [NSMutableArray array];
//创建临时的可变数组来接受遍历出来的字典数据
    for (NSDictionary *arrDict in dict[@"cars"]) {
        Cars *car = [Cars carsWithDict:arrDict];
//将字典赋值给cars的对象
        [tempDict addObject:car];
//再把字典添加到可变数组中
    }
    groups.cars = tempDict;
//将可变数组赋值给cars数组
    return groups;
}

模型搞定,接下来就来编写数据源的方法
首先UITableView有两种风格,一直是分组显示,一种是单组显示,上面的demo就是单组显示,因为单组显示的头部标题会一直停驻在控件的顶端显示,至于多组显示则不会,多组显示会有头部显示和尾部显示,头部标题也不会停在控件顶端显示,不信你看
dayEight05
怎么选择风格呢?
在storyboard中选中UITableView控件 然后Show the attributes inspector中的style选中,如下图
dayEight06
plain是单组显示,而Grouped是多组显示,至于这么选,看你的需求
接下来就看ViewController.m中的代码,如下

#import "ViewController.h"
#import "CarGroups.h"
#import "Cars.h"

@interface ViewController () <UITableViewDataSource>

@property (weak, nonatomic) IBOutlet UITableView *tableView;
//关联着外面控件的对象
@property (nonatomic, copy) NSArray *cars;
//用来接收全部数据数组
@end

static NSString *ID = @"car";
//ID标识符,用来识别缓存池中的UITableViewCell,待会介绍为什么要用这个
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

#pragma mark - carDate

- (NSArray *)cars
//懒加载
{
    if (!_cars) {
        NSArray *arrDict = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cars.plist" ofType:nil]];
//读取plist文件并加载到数组
        NSMutableArray *tempArr = [NSMutableArray array];
        for (NSDictionary *carDict in arrDict) {
            CarGroups *group = [CarGroups carGroupsWithDict:carDict];
            [tempArr addObject:group];
        }
        _cars = tempArr;
    }
    return _cars;
/*
以上算是一个把plist数据转换成模型的一个套路吧,先读取后遍历,然后一部分一部分赋值给对应的属性,最后再把遍历出来的字典添加到全部数据的数组
*/
}

#pragma mark - tableViewDateSource
//设置一共有多少组数据,数量即是数组元素的个数
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{

    return self.cars.count;
}
//设置每组有多少个行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    CarGroups *group = self.cars[section];
//先取出所有组的模型,再返回每组有多少车的数量
    return group.cars.count;
}
//每个cell的数据注入
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
//先看缓存池有没有ID标识的cell
    if (cell == 0) {
                        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
                        [self cargroupWithSeciotn:indexPath.section andRow:indexPath.row inCell:cell];
//如果没有创建一个带ID标识的cell并设置cell的风格,加载数据
    }else {
            [self cargroupWithSeciotn:indexPath.section andRow:indexPath.row inCell:cell];
//如果有,加载数据
    }
    return cell;

}
//加载数据的对象方法
- (void)cargroupWithSeciotn:(NSInteger)section andRow:(NSInteger)row inCell:(UITableViewCell *)cell
{
    CarGroups *group = self.cars[section];
//取出每组的数据
    Cars *car = group.cars[row];
//取出每行的数据
    cell.imageView.image = [UIImage imageNamed:car.icon];
//设置每行的图标
    cell.textLabel.text = car.name;
//设置每行的文字
}
//设置头部文件
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    CarGroups *group = self.cars[section];
    return group.title;
}
@end

为什么要弄缓冲池和标识符呢?因为UITableView的加载方式是每个cell进入到视野中就会调用一次

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

这个方法,这个方法中又有创建UITableViewCell对象的代码,如果离开了事业,cell就会被销毁,为了优化性能,所以弄了一个缓存池,让离开视野的cell不被销毁而进去该缓存池,如果继续往上/下拖动时,会先从缓存池中看是否有带标识符的cell(防止调用错误)如果有,将缓存池中的cell补进来然后设置数据,如果没有再创建新的cell,因为CSDN没办法上传gif所以没有进行滚动时的地址验证,有兴趣的朋友可以试一下,将会发现地址的数量永远是视野内的那几个+1.这样就避免了频繁创建对象/销毁对象,有利于改善用户体验

接下来再讲一点点UITableViewController的知识点,顾名思义,就是继承UITableViewControl,控件图片如下
dayEight09
接下来用另一个demo简单的叙述下,老规矩,上storyboard的截图

dayEight07

这个时候右键控件的,你会发现DateSource和Delegate都已经设置好了
dayEight08

这个时候只要创建一个类,继承UITableViewController 然后把storyboard与该类进行关联,然后就可以继续编写代码啦,demo截图如下
这里写图片描述
这个其实大概和上一个demo一样,都是吧plist数据转换成模型然后赋值给cell,但这里有一个cell的属性要说一下,之前的demo我们可以知道cell有imageView和titleText两个属性,其实cell还有另一个属性就是detailTextLabel,也就是图中那个价格,但使用这个属性时,必须在创建cell对象时,把cell的风格设置成UITableViewCellStyleSubtitle,例如代码

cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];

其他的设置头部标题和尾部标题其实很简单,去UITableViewDataSource的代理头文件中查找对应的方法即可,23:58分了,今天超级累,不熬夜,刷牙洗脸睡觉,明天得继续学习新的知识能,明天断更一天,周日更—————good night

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值