UITableView

继承自UIScrollView,性能极佳

  • UITableView的两种样式
  • UITableViewStylePlain列表样式
  • UITableViewStyleGrouped 分组样式

dataSource的代理

  • UITableView需要一个数据源datasource来显示数据
  • UITableView会向数据源查询一共有多少行数据以及每一行显示什么数据等
  • 没有设置数据源的UITableView只是个空壳
  • 凡是遵守UITableViewDataSource协议的OC对象,都可以是UITableView的数据源
设置数据源
方法1代码
ViewController添加协议UITableViewDataSource
@property(weak,nonatomic) IBOutlet UITableView *tableView;
self.tableView.dataSource = self;
方法二拖线
UITableView 右键 -> dataSource -> 拖到ViewController
实现协议的方法,有两个必须实现
//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return 1;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return 2;
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];cell.textLabel.text = @"hello";//cell.imageView//cell.detailTextLabel.textreturn cell;
}
  • cell的属性

cell.textLable.text显示文字
cell.imageView显示图片
cell.detailTextLabel.text显示小文字

  • cellStyle
    可以修改cell的多种显示

UITableView多组数据

先设置UITableViewStyleGrouped

//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return 3;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//根据不同组显示不同行数据
if(section == 0){return 3;}
else if(section == 1){return 2;}
else{return 1;}
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];if(indexPath.section == 0){//第一组if(indexPath.row == 0){cell.textLable.text = @"中国";}//第一行else if(indexPath.row == 1){cell.textLable.text = @"韩国";}//第二行else{cell.textLable.text = @"韩国";}
}
else if(indexPath.section == 1){if(indexPath.row == 0){cell.textLable.text = @"南非";}//第一行else(indexPath.row == 1){cell.textLable.text = @"索马里";}//第二行
}
else{cell.textLable.text = @"荷兰";}return cell;
}//每一组的标题显示什么
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{//section返回不同组的标题
if(section == 0){return @"亚洲";}
else if(section == 1){return @"非洲";}
else{return @"欧洲";}
}//每一组的描述,组尾
-(NSString *)tableView: (UITableView *)tableView titleForFooterInSection: (NSInteger)section{if(section == 0){return @"亚洲的描述";}
else if(section == 1){return @"非洲的描述";}
else{return @"欧洲的描述";}
}

动态加载plist文件到UITableView

MVC:plist转模型
先设置UITableViewStyleGrouped

#import <Foundation/Foundation.h>
@interface CZGroup: NSObject//组标题
@property(nonatomic,copy)NSString *title;
//组描述
@property(nonatomic,copy)NSString *desc;
//这组里面的汽车品牌信息
@property(nonatomic,strong)NSArray *cars;-(instancetype)initwithDict: (NSDictionary *)dict;
+(instancetype)groupWithDict: (NSDictionary *)dict;
@end@implementation CZGroup
-(instancetype)initwithDict: (NSDictionary *)dict
{  if(self=[super init])//调用父类的初始化{[self setValuesForKeysWithDictionary:dict];}return self;
}
+(instancetype)groupWithDict: (NSDictionary *)dict
{return [[self alloc]initWith:dict];}
@end
@property(nonatomic,strong)NSArray *groups;-(NSArray *)groups{if(_groups == nil){NSString *path = [[NSBundle mainBundle]pathForResource:@"car_simple.plist" ofType:nil];NSArray * arrayDict = [NSArray arrayWithContentsOfFile:path];NSMutableArray *arrayModel = [NSMutableArray array];for(NSDictionary *dict in arrayDict){GZGroup *model = [CZGroup groupWithDict:dict];[arrayModel addObject:model];}_group = arrayModel;}return _groups;
}
//告诉UITableView 显示几组,不实现默认分1组,可以不实现
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{return self.groups.count;
}//告诉UITableView每组显示几行数据,必须实现
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{//根据不同组显示不同行数据GZGroup *group = self.groups[section];return group.cars.count;
}//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{GZGroup *group = self.groups[indexPath.section];//第几组  NSString *brand = group.cars[indexPath.row];//第几行UITableViewCell *cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil];cell.textLabel.text = brand;cell.accessoryType = UITableViewCellAccessoryCheckmack;return cell;
}//每一组的标题显示什么
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{GZGroup *group = self.groups[section];return group.title;
}//每一组的描述,组尾
-(NSString *)tableView: (UITableView *)tableView titleForFooterInSection: (NSInteger)section{GZGroup *group = self.groups[section];return group.desc;
}
  • cell设置右边点击按钮
//多种选择,枚举
cell.accessoryType = UITableViewCellAccessoryCheckmack;//打钩
cell.accessoryType = UITableViewCellAccessoryDetailButton;//详情
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;//小箭头
类型是UIView
cell.accessoryView = [[UISwitch alloc] init];//可以自定义

UITableViewCell的常见属性

  • lmageView 显示图片

  • textLabel 显示文字

  • detailTextLabel 显示小文字

  • accessoryType 右边单元格类型选择

  • accessoryView 右边单元格自定义

  • backgroundColor设置单元格背景

  • backgroundView设置背景图片,可以指定一个UIImageView

  • selectedBackgroundView设置背景被选中图片

设置背景被选中改变颜色
UIView *bgView = [[UIView alloc] init];
bgView.backgroundColor = [UIColor greenColor];
cell.selectedBackgroundView = bgView;
  • rowheight 统一设置行高(也可以不设置)
self.tableView.rowheight = 60;
  • 每行行高不一致的设置方法
1.添加代理,<UITableViewDelegate>  跟Source不是同一个
2.代理方法
-(CGFloat)tableView:(tableview *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath{int rownum = indexpath.row;if(rownum %2 == 0) {return 60;}else{return 120;}
}
  • separatorColor 分割线颜色
self.tableView.separatorColor=[UIColor redColor];
  • separatorStyle 分割线样式
self.tableView.separatorStyle=UITableViewCellSeparatorStyleNone;//没有分割线
  • 设置分割线的Insets上下左右间距
[self.tableView setseparatorInset:UIEdgeInsetsMake(0,0,0,0)];
  • tableHeaderView 最上方一般可以放广告
  • tableFooterView 最下方一般可以放加载更多

UITableView的性能优化(cell的循环利用)

UITableView的加载数据的本质是,加载将要进入画面中的cell,释放离开画面的cell,但是需要多次重复的创建和释放对象

因为每次都创建一个单元格效率比较低,所以要对单元格进行重用,单元格重用的基本思路就是:

  • 1:在创建单元格的时候指定一个“重用ID”reuseIdentifier
  • 2:当需要一个新的单元格的时候,先去"缓存池”中根据“重用ID”reuseIdentifier去查找是否有可用的单元格
  • 如果有,则直接从缓存池中取出这个单元格,进行使用(修改这个单元格中显示的数据、样式 )
  • 如果没有需要的单元格,此时只能重新创建件一个单元格了

//告诉UITableView每一组的每一行显示什么单元格内容,必须实现
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *) indexPath{//声明一个static IDstatic NSString *ID = @"hero_cell";//根据这个重用ID去缓存池查找对应的CellUITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];//没有找到cell,那就重新创建一个//现在好像不需要这个步骤了,可以直接dequeueReusableCellWithIdentifier:ID就行了//if(cell==nil){// UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];//}return cell;
}

设置右侧索引

  • 实现右侧的索引栏,通过实现数据源协议的方法
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView

点击右侧索引栏中的文字,会根据索引的顾序跳转到左侧对应的位置,获取groups数组中的每个对象的tite值,并返回到一个NSArray中

//该方法运行一次
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{//返回array数组的每个元素对象的属性
return [self.groups valueForKeyPath:@"title"];
}

滚动到最后一行

NSIndexPath *idxPath = [NSIndexPath indexPathForRow:10 inSection:0];
//该行滚动到最上面
[self.tableView scrollToRowAtIndexPath:idxPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES]

代理监听点击cell

遵守UITableViewDelegate协议

代理方法:
//监听行被选中的代理方法
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath{NSLog(@"%ld",(long)indexPath.row);
}

代理监听滚动

  • 遵守代理协议
//滚动的时候执行该方法
-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{}

修改cell内容并刷新

找到数据源模型 -> 修改属性 -> 刷新tableView

NSString *name = @"text";
CZHero *hero = self.hero[0];
hero.name = name;//刷新数据,重载,全部刷新
[self.tableView reloadData];
//局部刷新,可以刷新指定的行或是组,不能用于添加数据后刷新
NSIndexPath *idxPath = [NSIndexPath indexPathForRow:1 inSection:0];//inSection组,Row行
[self.tableView reloadRowAtIndexPaths: idxPath withRowAnimation:UITableViewRowAnimationAutomaic];
//withRowAnimation枚举可以选择刷新动画

从别的控件修改,可以通过tag传值

xib自定义cell

  • 建一个空的xib文件 -> 添加cell控件 -> cell控件内自己添加
  • 参考iOS开发之UI开发2 -> xib
  • 可重用ID可以在xib文件中修改identifier,或者代码实现

tableFooterView最下方的view

tableFooterView的frame只能修改x和height的值,Y和width不能修改

ActivityindicatorView加载指示器

  • ActivityindicatorView转动ActivityindicatorView -> Behavior -> Animating

UITableViewController

可以替代ViewController,tableView和代理已经设置好了

  • 设置ViewController -> is inltial View Controller 为启动控制器
  • 设置UITableViewControllerclass继承自UITableViewController

自定义cell

  • 继承自UITableViewCell
  • 重写构造函数
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentfier{if(self = [super initWithStyle:style reuseIdentifier:reuseIdentfier]){//添加组件UIImageView *imgViewIcon = [[UIImageView alloc] init];[self.contentView addSubview:imgViewIcon];...}return self;
}
-(void)settingData{//转模型时判定是否有,有就展示出来if(model.piture){self.imgViewpicture.image = [UIImage imageNamed:model.picture];self.imgViewpicture.hidden = NO;}else{self.imgViewpicture.hidden = YES;}...}
-(void)setView{[self settingdata];
}

计算文字NSSrting的frame

  • 根据昵称的文字计算昵称label的宽和高
  • 影响昵称Label的高和宽的因素:字体大小、文字多少、高度取决于是否固定了宽度(是否限制了最大的宽度和高度)
CGSize name = [字符串对象 boundingRectWithSize: CGSizeMake(MAXFLOAT,MAXFLOAT) options: NSStringDrawingUsesLineFragmentOrigi attributes: @{NSFontAttributeName:[UIFont systemFontOfSize:12]} context: nil].size;CGFloat nameW = name.width;
CGFloat nameH = name.height;boundingRectWithSize:最大的大小,一般取CGSizeMake(MAXFLOAT,MAXFLOAT),没有限制
options:计算方式
attributes:获取字体大小,存放字典形式,@{NSFontAttributeName:[UIFont systemFontOfSize:12]}
  • 保证这里计算的时候使用的字体大小和创建Label时设置的字体大小一致,使用一个宏来统一设置
  • 根据呢称Label的宽和高,计算x和y

进阶:可以为NSString加类方法,更加方便

-(CGSize)size0fTextWithMaxSize:(CGSize)maxSize font:(UIFont *)font{NSDictionary *attrs =@{NSFontAttributeName:font};return [self boundingRectWithSize:maxSize options:NSStringDrawingUsesLineFragmentOrigin attributes: attrs context: nil].size;}+(CGSize)sizeWithText:(NSString *)text maxSize: (CGSize)maxSize font: (UIFont*)font{[text sizeOfTextWithMaxSize:maxSize font:font];
}

计算cell的高度

  • 需要先算完再生成cell,所以需要提前到懒加载的时候,把行高等数据先算好
  • 写一个modelViewmodel成为他的属性之一,懒加载时全部计算好
CGFloat rowHeight = 0;
//判断是否有最后一个组件,由最后一个组件的Y决定
if(self.weibo.picture){rowHeight = CGRectGetMaxY(self.imgViewPicture.frame)+margin;
}else{rowHeight = CGRectGetMaxY(self.lblText.frame)+margin;
}
//返回行高
-(CGFloat)tableView:(tableview *)tableView heightForRowAtIndexPath:(NSIndexPath *) indexPath{CZFrame *frame = self.Frames[indexPath.row];return frame.rowHeight;
}

统一设置每组标题的行高

  • 控制器viewDidLoad方法
-(void)viewDidLoad{[super viewDidLoad];//统一设置每组的组标题的高度self.tableView.sectionHeaderHeiaht = 44;
}

取消UITabelView的选中高亮

tableView.allowsSelection = NO;

静态UITableView

就是代码写死的UITableView,在storyboard里面设计

  • 在设置content选择static cell,需要注意的是,需要使用UITableViewController,而不是ViewController

设置titleForHeader的两种形式

//方法一:设置每一组的标题
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInsection: (NSInteger)section{GZGroup *group = self.groups[section];return group.title;
}

-为了重用,这里建议使用UITableViewHeaderFooterViewcell外,headerfooter都要遵循重用模式

//方法二:带有控件的标题
-(UIView *)tableView:(UITableView *)tableview viewForHeaderInsection:(NSInteger)section{GZGroup *group = self.groups[section];  //为了重用,这里建议使用UITableViewHeaderFooterView,可以将其封装//声明一个static IDstatic NSString *ID = @"group_header_view";//根据这个重用ID去缓存池查找对应的headerVm UITableViewHeaderFooterView *headerVm = [tableView dequeueReusableHeaderFooterViewWithIdentifier:ID];//没有找到headerVm,那就重新创建一个if(headerVm == nil){headerVm  = [[UITableViewHeaderFooterView alloc] initWithReuseIdentifier:ID];}//设置数据return headerVm;
}

控件的frame发生改变调用的方法

-(void)layoutSubviews{[super layoutSubviews];
//自己的代码
}

下拉刷新

  • UITableView设置 -> refreshing -> 启用 ->方法返回值改为IBAction ->
    控件和方法进行连线

连线完默认设置下拉执行self.refreshControl的开始执行方法

  • ViewController中重写方法
self.refreshControl.tintColor = [UIColor blueColor];
self.refreshControl.attributedTitle = [[NSAttributedString alloc]initWithString:@:"正在加载..." attributes:@{NSForegroundColorAttributeName:[UIColor redColor]}];
  • 刷新结束执行该方法
[self.refreshControl endRefreshing];

cell左滑删除

让tableView进入编辑模式,新增代理方法

-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{//点击哪个cell的delete,就执行//数据源中删除该行//可以刷新tableView,也可以执行这个方法,会有动画//deleteRowAtIndexPaths:是Array类型//withRowAnimation:动画效果自己选[self.tableView deleteRowAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationLeft];//该方法执行完会自动比较数据源和显示出来的数据量是否一致(务必先删除模型)//删除方法
}

xib中Cell的复用

//在viewDidLoad中注册
[tableView registerNib:[UINib nibWithNibName:@"FDBlackListTableCell" bundle:nil] forCellReuseIdentifier:@"FDBlackListTableCell"];
//代理方法中
FDBlackListTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"FDBlackListTableCell"];
cell.selectionStyle = UITableViewCellSelectionStyleNone;

iOS开发之UI开发(UITableView)相关推荐

  1. IOS开发之UI基础LOL英雄展示-15

    IOS开发之UI基础LOL英雄展示-15 // // ViewController.m // 15-英雄展示-单组数据 // // Created by 鲁军 on 2021/2/3. //#impo ...

  2. (0010) iOS 开发之UI布局兼容 4s/5/6/7 屏幕解决方案

    iOS开发技术分享群 147787076 如上带标注的效果图,是1080*1920 也就是6p 的尺寸.如何根据6p的标注,在各种iPhone 尺寸上完美适配尼? 适用:UI 各屏幕/分辨率适配方案( ...

  3. iOS开发之SDK开发

    转自 https://www.jianshu.com/p/cbb1f54b89d2 内容提要:不同场景下如何封装及开发SDK .a静态库创建 直接创建Framework库 在已有工程中创建 创建Fra ...

  4. (0107)iOS开发之UI实时调试InjectionIII的使用

    AppStore : 下载:Injectionlll 下载地址 使用步骤: 1.设置InjectionIII 打开InjectionIII工具,选择Open Project,选择你的代码所在的路径,然 ...

  5. IOS开发之UI手势

    2019独角兽企业重金招聘Python工程师标准>>> 点击手势和双击手势 #import "TapViewController.h" @interface Ta ...

  6. (0061)iOS开发之iPad开发:UISplitViewController分割视图控制器

    //分割试图控制器 左侧默认320宽度 右侧self.view.frame.size-320 @property (strong,nonatomic)UISplitViewController *sp ...

  7. iOS开发之AVKit框架使用

    2019独角兽企业重金招聘Python工程师标准>>> iOS开发之AVKit框架使用 一.引言 在iOS开发框架中,AVKit是一个非常上层,偏应用的框架,它是基于AVFounda ...

  8. 李洪强iOS开发之RunLoop的原理和核心机制

    李洪强iOS开发之RunLoop的原理和核心机制 搞iOS之后一直没有深入研究过RunLoop,非常的惭愧.刚好前一阵子负责性能优化项目,需要利用RunLoop做性能优化和性能检测,趁着这个机会深入研 ...

  9. iOS开发之ARC(自动引用计数)

    iOS开发之ARC(自动引用计数) 英文原文:Automatic Reference Counting on iOS 参与翻译(4人): 纶巾客, showme, 李远超, 王宇龙 自动引用计数(AR ...

最新文章

  1. 【BZOJ】1299: [LLH邀请赛]巧克力棒
  2. vscode中调试react
  3. 使用response的outputstream
  4. java jbutton 不显示_java – JButton中的图像未显示
  5. easyexcel 设置标题_使用easyexcel完成复杂表头及标题的导出功能(自定义样式)
  6. 【ElasticSearch】Es 源码之 Exporters 源码解读
  7. 论文公式编号右对齐_如何编辑处理论文中的公式
  8. 开源cnc软件_带有开源软件的CNC铣削
  9. Layui表格点击详情
  10. 用C语言实现推箱子小游戏基础程序
  11. 设计网站制作步骤是什么?一个好的网站制作标准是怎样的?
  12. mysql创建新用户
  13. 爬壁机器人外文文献_仿生爬壁机器人的研究现状
  14. 如何与宜家IKEA建立EDI连接?
  15. CVPR 2020 开幕!最佳论文奖等揭晓!
  16. 计算机主板上一般带有高速缓冲存储器cache,它是与什么之间的缓存,计算机微机原理与应用(一)...
  17. android 仿简书评论,Android 开发仿简书登录框可删除内容或显示密码框的内容
  18. python最大递归层次_练习题-Python的最大递归层数
  19. HSV与RGB之间相互转换
  20. Win10 x64 中VC6 安装卡死、无法单步调试、调试退出进程没有结束

热门文章

  1. 1433,3306,3389端口的利用
  2. 择校秘籍|北邮计算机 和 同济计算机 应该怎么选?
  3. Duan2baka的各种LCA模板!
  4. springMVC实现form表单数据+文件提交
  5. 诗意的栖居于地球之上
  6. 苹果史上最大交易:斥资30亿美元收购Beats
  7. 神话欧巴都转让商标了,我们还等什么
  8. JAVA——界面设计Swing教程
  9. Python 命令行进度条
  10. springboot实现图片上传到又拍云中,并且保存图片外连接路径到数据库,外连接也可访问图片(一)