iOS中TableView如何统一数据源代理详解

前言

TableView 是 iOS 应用程序中非常通用的组件,几乎每一个界面都有一个TableView,而我们许多的代码都和TableView有关系,比如数据展示、更新TableView,一些响应选择事件等,而这些大多都会通过其代理函数来实现,所以在VC中我们通常需要实现大量TableView的代理函数,如下面这样

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
 return 12.0
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
 return 0.01
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
 return 44.0
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
 return nil
}
func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
 return nil
}
func numberOfSections(in tableView: UITableView) -> Int {
 return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
 return 10
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
 return UITableViewCell()
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
 tableView.deselectRow(at: indexPath, animated: true)
}

如果上面的代码在每个VC中都实现一次,不仅写了很多的重复的代码,还增加了VC的复杂度,所以我在想能不能有一个统一的代理类,我们的TableView只要遵循它,就不用每次都要写一大堆的代理方法,下面就是我写的一个代理类的使用

示例代码

 private var delegate = CCDataSource()

 lazy private var tableView: UITableView = {
  let table = UITableView(frame: self.view.bounds, style: .grouped)
  // 1.注册cell
  table.register(Custom1Cell.self, forCellReuseIdentifier: "cell1")
  table.register(Custom2Cell.self, forCellReuseIdentifier: "cell2")
  // 2.代理
  table.delegate = self.delegate
  table.dataSource = self.delegate
  return table
 }()

 override func viewDidLoad() {
  super.viewDidLoad()
  self.view.addSubview(tableView)
  self.setupTableView()
  self.loadData()
 }

 private func loadData() {
  // 3.网络请求数据源,并赋值
  delegate.datas = [[Model1(),Model1(),Model1()],[Model2(),Model2(),Model2(),Model2()]]
  // 4.刷新视图
  tableView.reloadData()
 }

 private func setupTableView() {
  // 在这里实现TableView的代理
  delegate.identifier { (indexPath) -> (String) in
   // 5.确定cell的类型
   return indexPath.section == 0 ? "cell1" : "cell2"
  }.headerHeight { (section) -> (CGFloat) in
   // 6.头部高度
   return 12.0
  }.footerHeight { (section) -> (CGFloat) in
   // 7.尾部高度
   return 0.01
  }.rowHeight{ (indexPath, data) -> (CGFloat) in
   // 8.行高
   if let model = data as? Model1 {
    return model.height()
   }
   if let model = data as? Model2 {
    return model.height()
   }
   return 44.0
  }.setContentCell { (cell, data) -> (Void) in
   // 9.配置数据源
   if let item = cell as? Custom1Cell, let model = data as? Model1 {
    item.textLabel?.text = "Custom1Cell" + model.description
   }
   if let item = cell as? Custom2Cell, let model = data as? Model2 {
    item.textLabel?.text = "Custom2Cell" + model.description
   }
  }.selected {[weak self] (indexPath, data) -> (Void) in
   // 10.点击事件(这里[weak self]需要防止循环引用)
   self?.navigationController?.pushViewController(ViewController(), animated: true)
  }
 }
  1. 注册cell:这一步很重要,这个代理类只支持这种方式加载cell,你在该界面有几种cell,就需要注册几个cell类
  2. 代理: 将代理实例赋值给tableView的代理,这里我将dataSource和delegate统一为delegate了,并且如果有多个TableView,我们还可以创建多个代理实例与其一一对应
  3. 网络请求:这里是做网络请求地方,并且将请求后的数据保存在代理类中
  4. 刷新视图
  5. 确定cell的类型:cell是通过它注册identifier来创建的,所以根据indexPath来返回相应的cell注册的identifier即可
  6. 头部高度:header的高度,可以是定值,也可以根据section来动态返回
  7. 尾部高度:footer的高度,可以是定值,也可以根据section来动态返回
  8. 行高:这里的行高可以通过data来获取,这样利于做高度缓存,也可以通过indexPath来动态返回
  9. 配置数据源:这里可以获取的已经初始化号的cell和其对应的数据源,我们只需要将其赋值给cell即可
  10. 点击事件

上面这些步骤也不是固定的,这里有链式编程的思想,有些属性可以不设置则会取默认值,当然也可以重复设置,不过此时后面的会覆盖前面的

通过上面的方法,我们只需要创建一个CCDataSource实例,就可以在一个方法中将所有的TableView代理实现,而且在第5步时,我们就将cell与data对应起来了,后面会减少很多复杂的if else判断,这不仅减少了代码量,同时也使实现逻辑更加清晰

Demo地址:https://github.com/cdcyd/CCDataSource (本地下载)

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • IOS实现左右两个TableView联动效果

    一.先来看看要实现的效果图 二.小解析,可以先看看后面的! 三.实现 tableView联动 主要分两种状况 1.点击 左侧 cell 让右侧 tableView 滚到对应位置 2.滑动 右侧 tableView 让左侧 tableView 滚到对应位置 1.先实现简单的:点击 左侧 cell 让右侧 tableView 滚到对应位置 //MARK: - 点击 cell 的代理方法 - (void)tableView:(UITableView *)tableView didSelectRowAt

  • 解决iOS11刷新tableview会出现漂移的现象

    首先要注意这只是在iOS11下会出现的bug,如果iOS10以及以下也有问题的情况不属于此列 问题的动图如下所示,如果要做每隔一段短时间就刷新一个section甚至整个tableview的操作的时候会出现闹鬼式的不断移动. 它真的是自己回去的~(限制动图2M真的有点烦) 解决方案 在初始化tableview的时候加上这几行 _tableview.estimatedRowHeight = 0; _tableview.estimatedSectionHeaderHeight = 0; _tablev

  • 详解iOS开发中UItableview控件的数据刷新功能的实现

    实现UItableview控件数据刷新 一.项目文件结构和plist文件 二.实现效果 1.说明:这是一个英雄展示界面,点击选中行,可以修改改行英雄的名称(完成数据刷新的操作). 运行界面: 点击选中行: 修改数据后自动刷新: 三.代码示例 数据模型部分: YYheros.h文件 复制代码 代码如下: // //  YYheros.h //  10-英雄展示(数据刷新) // //  Created by apple on 14-5-29. //  Copyright (c) 2014年 itc

  • iOS开发之TableView实现完整的分割线详解

    前言 在我们创建一个tableView的时候,细心的你有没有发现UITableViewCell左侧会有空白.而我们在开发中有这样的需求: 需要一根完整的分割线(去掉烦人的空白部分, 即分割线的宽度 == 屏幕的宽度). 那么下面我就讲一讲该如何去掉空白的部分,显示完整的分割线. 这里我提供两种方法 : 第一种方法,也是我们最常用的方法,也是在我们自定义cell的时候所用到的. 即去掉tableView默认的分割线,自定义cell,重写setFrame: 方法即可 下面是具体代码实现: 步骤一 :

  • iOS tableView实现单选和多选的实例代码

    今天在项目中遇到了tableView的单选需求,现在总结一下,用一个简单的demo实现了简单的单选和多选两个功能.先看下效果图: 1:首先实现下单选 1:使用一个变量记录选中的行 @property (assign, nonatomic) NSIndexPath *selIndex; //单选选中的行 2:设置tableView数据,共2组,每组10行, - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { ret

  • iOS中TableView如何统一数据源代理详解

    前言 TableView 是 iOS 应用程序中非常通用的组件,几乎每一个界面都有一个TableView,而我们许多的代码都和TableView有关系,比如数据展示.更新TableView,一些响应选择事件等,而这些大多都会通过其代理函数来实现,所以在VC中我们通常需要实现大量TableView的代理函数,如下面这样 func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat

  • IOS 中CALayer绘制图片的实例详解

    IOS 中CALayer绘制图片的实例详解 CALayer渲染内容图层.与UIImageView相比,不具有事件响应功能,且UIImageView是管理内容. 注意事项:如何使用delegate对象执行代理方法进行绘制,切记需要将delegate设置为nil,否则会导致异常crash. CALayer绘制图片与线条效果图: 代码示例: CGPoint position = CGPointMake(160.0, 200.0); CGRect bounds = CGRectMake(0.0, 0.0

  • iOS中setValue和setObject的区别详解

    网上关于setValue和setObject的区别的文章很多,说的并不准确,首先我们得知道: setObject:ForKey: 是NSMutableDictionary特有的:setValue:ForKey:是KVC的主要方法 话不多说,上代码: - (void)viewDidLoad { [super viewDidLoad]; //setObject和setvalue的区别 NSMutableDictionary *dic = [NSMutableDictionary dictionary

  • IOS 中KVC的使用方法实例详解

    IOS 中KVC的使用方法实例详解 KVC是Key Value Coding的缩写,意思是键值编码.在iOS中,提供了一种方法通过使用属性的名称(也就是Key)来间接访问对象的属性方法.说的有的拗口,实际上就是通过类定义我们可以看到类的各种属性,那么使用属性的名称我们就能访问到类实例化后的对象的这个属性值. 这个方法可以不通过getter/setter方法来访问对象的属性.因为一个类的成员变量如果没有提供getter/setter的话,外界就失去了对这个变量的访问渠道.而KVC则提供了一种访问的

  • iOS中利用CAEmitterLayer实现粒子动画详解

    前言 你肯定见过很酷炫的iOS动画吧,例如微信的表情雨

  • CentOS 7中使用Squid提供HTTP代理详解

    本文主要记录了一下设置CentOS服务器使用Squid作为HTTP代理,及客户端的代理配置的方法,下面来看看详细的介绍吧. 使用Squid提供HTTP代理 主机上安装和设置Squid 作为网关的n147机器,公网IP是2.2.2.147.安装Squid,然后修改配置,启用服务. yum install -y squid # squid的配置文件在 /etc/squid/squid.conf,修改内容可参考下面的Dockerfile # 修改配置后,初始化squid的工作目录 squid -z #

  • 如何在iOS中高效的加载图片详解

    目录 前言 图片的渲染流程 DataBuffer SD源码分析 ImageBuffer 占用内存大小 Xcode测试 如何减少图像占用内存 向下采样 SD源码分析解码过程 选择正确的图片渲染格式 渲染格式 如何正确的选择渲染格式 减少后备存储器的使用 减少或者不使用 draw(rect:) 方法 如何在列表中加载图片 线程爆炸 总结 前言 在iOS开发中,图片(UIImage)是我们在开发中,占用手机内存比较大的对象,如果在运行过程中,内存占用过大,对电池寿命会造成影响,如果超过了内存占用的最大

  • iOS中捕获日志与异常示例详解

    前言 在平时自己调试的时候,可以直接连接电脑,直接在窗口中查看结果.但是在测试人员测试,或者灰度测试的时候,怎么才能拿到日志呢?最先想到的肯定是输出到本地文件,然后在需要的时候进行上传. 分享一段之前找到的方法,下面的代码提供了两个主要功能: – 把日志输出到文件中 – 捕捉异常信息 [解析都写在注释中了] 示例代码 - (void)redirectNSLogToDocumentFolder { //如果已经连接Xcode调试则不输出到文件 //该函数用于检测输出 (STDOUT_FILENO)

  • iOS中视频播放器的简单封装详解

    前言 如果仅仅是播放视频两者的使用都非常简单,但是相比MediaPlayer,AVPlayer对于视频播放的可控制性更强一些,可以通过自定义的一些控件来实现视频的播放暂停等等.因此这里使用AVPlayer的视频播放. 视频播放器布局 首先使用xib创建CLAVPlayerView继承UIView用来承载播放器,这样我们在外部使用的时候,直接在控制器View或者Cell上添加CLAVPlayerView即可,至于播放器播放或者暂停等操作交给CLAVPlayerView来管理.下面来看一下CLAVP

  • iOS中屏幕亮度与闪光灯控制详解

    本文主要介绍的是关于iOS屏幕亮度与闪光灯控制的相关内容,分享出来供大家参考学习,下面来看看详细的介绍: 所用涉及框架:AVFoundation框架和ImageIO 读取屏幕亮度: [UIScreen mainScreen].brightness; 设置屏幕亮度: [[UIScreen mainScreen] setBrightness:0.5]; 获取环境亮度主要代码: - (void)getTorch { AVCaptureDevice *device = [AVCaptureDevice

随机推荐