IOS开发——UI进阶篇—UITableView,索引条,汽车数据展示案例

一、什么是UITableView



在iOS中,要实现展示列表数据,最常用的做法就是使用UITableView
UITableView继承自UIScrollView,因此支持垂直滚动,而且性能极佳

UITableView的两种样式
UITableViewStylePlain
UITableViewStyleGrouped

二、如何展示数据



UITableView需要一个数据源(dataSource)来显示数据

UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等

没有设置数据源的UITableView只是个空壳

凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源

tableView展示数据的过程
调用数据源的下面方法得知一共有多少组数据
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;

调用数据源的下面方法得知每一组有多少行数据
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;

调用数据源的下面方法得知每一行显示什么内容
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;

三、Cell简介



UITableView的每一行都是一个UITableViewCell,通过dataSource的tableView:cellForRowAtIndexPath:方法来初始化每一行

UITableViewCell内部有个默认的子视图:contentView,contentView是UITableViewCell所显示内容的父视图,可显示一些辅助指示视图

辅助指示视图的作用是显示一个表示动作的图标,可以通过设置UITableViewCell的accessoryType来显示,默认是UITableViewCellAccessoryNone(不显示辅助指示视图),其他值如下:
UITableViewCellAccessoryDisclosureIndicator
UITableViewCellAccessoryDetailButton
UITableViewCellAccessoryDetailDisclosureButton
UITableViewCellAccessoryCheckmark

还可以通过cell的accessoryView属性来自定义辅助指示视图(比如往右边放一个开关)

四、UITableViewCell的contentView



contentView下默认有3个子视图
其中2个是UILabel(通过UITableViewCell的textLabel和detailTextLabel属性访问)
第3个是UIImageView(通过UITableViewCell的imageView属性访问)
UITableViewCell还有一个UITableViewCellStyle属性,用于决定使用contentView的哪些子视图,以及这些子视图在contentView中的位置
UITableViewCellStyleDefault
UITableViewCellStyleSubtitle
UITableViewCellStyleValue1
UITableViewCellStyleValue2

五、Cell的重用原理



iOS设备的内存有限,如果用UITableView显示成千上万条数据,就需要成千上万个UITableViewCell对象的话,那将会耗尽iOS设备的内存。要解决该问题,需要重用UITableViewCell对象

重用原理:当滚动列表时,部分UITableViewCell会移出窗口,UITableView会将窗口外的UITableViewCell放入一个对象池中,等待重用。当UITableView要求dataSource返回UITableViewCell时,dataSource会先查看这个对象池,如果池中有未使用的UITableViewCell,dataSource会用新的数据配置这个UITableViewCell,然后返回给UITableView,重新显示到窗口中,从而避免创建新对象

还有一个非常重要的问题:有时候需要自定义UITableViewCell(用一个子类继承UITableViewCell),而且每一行用的不一定是同一种UITableViewCell,所以一个UITableView可能拥有不同类型的UITableViewCell,对象池中也会有很多不同类型的UITableViewCell,那么UITableView在重用UITableViewCell时可能会得到错误类型的UITableViewCell

解决方案:UITableViewCell有个NSString *reuseIdentifier属性,可以在初始化UITableViewCell的时候传入一个特定的字符串标识来设置reuseIdentifier(一般用UITableViewCell的类名)。当UITableView要求dataSource返回UITableViewCell时,先通过一个字符串标识到对象池中查找对应类型的UITableViewCell对象,如果有,就重用,如果没有,就传入这个字符串标识来初始化一个UITableViewCell对象

Cell的重用代码
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// 1.定义一个cell的标识
static NSString *ID = @”czcell";

// 2.从缓存池中取出cell
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];

// 3.如果缓存池中没有cell
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
}

六、通过代码自定义cell(cell的高度不一致)



1.新建一个继承自UITableViewCell的类
2.重写initWithStyle:reuseIdentifier:方法
添加所有需要显示的子控件(不需要设置子控件的数据和frame,  子控件要添加到contentView中)
进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
3.提供2个模型
数据模型: 存放文字数据\图片数据
frame模型: 存放数据模型\所有子控件的frame\cell的高度
4.cell拥有一个frame模型(不要直接拥有数据模型)
5.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
6.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)

七、利用UITableView展示汽车数据案例


  1 #import <UIKit/UIKit.h>
  2 @interface ViewController : UITableViewController
  3 @end
  4
  5 /*************** ViewController**********************/
  6 #import "ViewController.h"
  7 #import "CarGroup.h"
  8 #import "Car.h"
  9
 10 #define chgID @"chgCell"
 11
 12 @interface ViewController ()
 13 @property (nonatomic, copy) NSArray *cargroups;
 14 @end
 15
 16 @implementation ViewController
 17
 18 - (void)viewDidLoad {
 19     [super viewDidLoad];
 20
 21     // 设置右边索引文字的颜色
 22     self.tableView.sectionIndexColor = [UIColor redColor];
 23
 24     // 设置右边索引文字的背景色
 25     self.tableView.sectionIndexBackgroundColor = [UIColor blackColor];
 26
 27     // 注册带有“chgCell”标识的cell
 28     [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:chgID];
 29
 30 }
 31
 32 // 重写cargroups的get方法
 33 - (NSArray *)cargroups
 34 {
 35     if (nil == _cargroups) {
 36         // 加载cars.plist文件
 37         NSString *path = [[NSBundle mainBundle] pathForResource:@"cars" ofType:@"plist"];
 38         NSArray *carGroupsdictArray = [NSArray arrayWithContentsOfFile:path];
 39
 40
 41         // 创建模型数组
 42         NSMutableArray *carGroupsM = [NSMutableArray array];
 43         // 字典转模型 将模型装入数组_cargroups中
 44         for (NSDictionary *cardict in carGroupsdictArray) {
 45             CarGroup *carg = [CarGroup carGroupWithdict:cardict];
 46             [carGroupsM addObject:carg];
 47         }
 48         _cargroups = carGroupsM;
 49     }
 50     return _cargroups;
 51 }
 52
 53 // 总共多少组
 54 - (NSInteger)numberOfSectionsInTableView:(nonnull UITableView *)tableView
 55 {
 56     return self.cargroups.count;
 57 }
 58
 59 // 每组多少行
 60 - (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 61 {
 62     return [self.cargroups[section] cars].count;
 63 }
 64
 65  // 加载每一行的cell(cell要显示的内容)
 66 - (UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath
 67 {
 68     // 1、从缓存池获取cell
 69     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:chgID];
 70     cell.backgroundColor = [UIColor yellowColor];
 71     // 2、如果没找到就创建一个新的cell
 72 //    if (nil == cell) {
 73 //        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
 74 //    }
 75
 76     CarGroup *carGroups = self.cargroups[indexPath.section];
 77     Car *car = carGroups.cars[indexPath.row];
 78
 79     // 3、给cell赋值
 80     cell.textLabel.text = car.name;
 81     cell.imageView.image = [UIImage imageNamed:car.icon];
 82
 83     return cell;
 84 }
 85
 86 // 设置头部内容
 87 - (NSString *)tableView:(nonnull UITableView *)tableView titleForHeaderInSection:(NSInteger)section
 88 {
 89     CarGroup *carGroups = self.cargroups[section];
 90     return carGroups.title;
 91 }
 92
 93 // 设置索引条
 94 - (nullable NSArray<NSString *> *)sectionIndexTitlesForTableView:(nonnull UITableView *)tableView
 95 {
 96     return [self.cargroups valueForKeyPath:@"title"];
 97 }
 98
 99 - (BOOL)prefersStatusBarHidden
100 {
101     return YES;
102 }
103
104 @end
105
106 /*************** CarGroup**********************/
107 #import <UIKit/UIKit.h>
108
109 @interface CarGroup : UIView
110
111 @property (nonatomic, copy) NSString *title;
112 @property (nonatomic, strong) NSArray *cars;
113
114 + (instancetype)carGroupWithdict:(NSDictionary *)dict;
115
116 @end
117
118 #import "CarGroup.h"
119 #import "Car.h"
120 @implementation CarGroup
121
122 + (instancetype)carGroupWithdict:(NSDictionary *)dict
123 {
124     CarGroup *carg = [[CarGroup alloc] init];
125     carg.title = dict[@"title"];
126
127     NSMutableArray *arrM = [NSMutableArray array];
128     for (NSDictionary *cardic in dict[@"cars"]) {
129         Car *car = [Car carWithDict:cardic];
130         [arrM addObject:car];
131     }
132     carg.cars = arrM;
133
134     return carg;
135 }
136
137 @end
138
139
140 /*************** Car**********************/
141 #import <UIKit/UIKit.h>
142
143 @interface Car : UIView
144
145 @property (nonatomic, copy) NSString *name;
146 @property (nonatomic, copy) NSString *icon;
147
148 + (instancetype)carWithDict:(NSDictionary *)dict;
149 @end
150
151 #import "Car.h"
152
153 @implementation Car
154
155
156 + (instancetype)carWithDict:(NSDictionary *)dict
157 {
158     Car *car = [[Car alloc] init];
159     [car setValuesForKeysWithDictionary:dict];
160
161     return car;
162 }
163 @end

总结:待更新。。。。

时间: 2024-08-02 19:19:15

IOS开发——UI进阶篇—UITableView,索引条,汽车数据展示案例的相关文章

IOS开发——UI进阶篇(十五)Quartz2D介绍

一.Quartz2D简介 1.什么是Quartz2DQuartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统 Quartz 2D能完成的工作绘制图形 : 线条\三角形\矩形\圆\弧等绘制文字绘制\生成图片(图像)读取\生成PDF截图\裁剪图片自定义UI控件 2.Quartz2D实例Quartz 2D能做很多强大的事情,例如 裁剪图片 涂鸦\画板 手势解锁 报表:折线图\饼状图\柱状图 二.自定义view 1.Quartz2D在iOS开发中的价值为了便于搭建美观的UI界面,iOS提供了UI

IOS开发——UI进阶篇(五)通知、代理、kvo的应用和对比,购物车

一.通知 1.通知中心(NSNotificationCenter)每一个应用程序都有一个通知中心(NSNotificationCenter)实例,专门负责协助不同对象之间的消息通信任何一个对象都可以向通知中心发布通知(NSNotification),描述自己在做什么.其他感兴趣的对象(Observer)可以申请在某个特定通知发布时(或在某个特定的对象发布通知时)收到这个通知 2.通知(NSNotification)一个完整的通知一般包含3个属性:- (NSString *)name; // 通知

IOS开发——UI进阶篇(十八)核心动画小例子,转盘(裁剪图片、自定义按钮、旋转)图片折叠、音量震动条、倒影、粒子效果

一.转盘(裁剪图片.自定义按钮.旋转) 1.裁剪图片 将一张大图片裁剪为多张 // CGImageCreateWithImageInRect:用来裁剪图片 // image:需要裁剪的图片 // rect:裁剪图片的尺寸,传递是像素 CGImageRef norImage = CGImageCreateWithImageInRect(norBigImage.CGImage, clipRect); 2.每次点击按钮立马变为选中状态,并且取消上次的按钮的选中状态 当然还要重写- (void)setH

IOS开发——UI进阶篇(十七)CALayer,核心动画基本使用

一.CALayer简介 1.CALayer在iOS中,文本输入框.一个图标等等,这些都是UIView你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层 在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,retain) CALayer *layer; 当UIView需

IOS开发——UI进阶篇(十)导航控制器、plist存储、微博详情页

一.导航控制器出栈 1.initWithRootViewController本质 UIViewController *vc = [[OneViewController alloc] init]; // 创建导航控制器 // 导航控制器必须要有一个根控制器 UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:vc]; // 会调用push方法 // initWithRoot

iOS开发——UI进阶篇(十九)UISearchBar控件简介

最近用到搜索功能.总结一下 搜索,无疑可以使用UISearchBar控件! 那就先了解一下UISearchBar控件吧! UISearchBar控件就是要为你完成搜索功能的一个专用控件.它集成了很多你意想不到的功能和特点! 首先,还是来普及一下UISearchBar控件API相关的属性和方法吧! UISearchBar属性相关 _searchBar = [[UISearchBar alloc] initWithFrame:CGRectZero];// 初始化,不解释 [self.searchBa

IOS开发——UI进阶篇(十六)Quartz2D实战小例子

一.画线 只有在drawRect中才能获取到跟view相关联的上下文 - (void)drawRect:(CGRect)rect {} 一条线 // 1.获取跟当前View相关联的layer上下文(画板) // 总结:目前获取的所有上下文都是以UIGraphics开头 // CGContextRef:上下文类型 // CG:CoreGraphics Ref:引用 CGContextRef ctx = UIGraphicsGetCurrentContext(); // 2.绘制内容,拼接路径 //

IOS开发——UI进阶篇(七)程序启动原理

一.Info.plist常见的设置 1.建立一个工程后,会在Supporting files文件夹下看到一个“工程名-Info.plist”的文件,该文件对工程做一些运行期的配置,非常重要,不能删除 在旧版本Xcode创建的工程中,这个配置文件的名字就叫“Info.plist” 项目中其他Plist文件不能带有“Info”这个字眼,不然会被错认为是传说中非常重要的“Info.plist” 项目中还有一个InfoPlist.strings的文件,跟Info.plist文件的本地化相关 2.常见属性

IOS开发——UI进阶篇(十二)事件处理,触摸事件,UITouch,UIEvent,响应者链条,手势识别

触摸事件 在用户使用app过程中,会产生各种各样的事件 一.iOS中的事件可以分为3大类型 触摸事件加速计事件远程控制事件 响应者对象在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件.我们称之为“响应者对象” UIApplication.UIViewController.UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件 二.UIResponder UIResponder内部提供了以下方法来处理事件触摸事件- (v