SkillAgentSearch skills...

GYTableViewController

A simple and efficient table control with pull-to-refresh

Install / Use

/learn @gaoyangclub/GYTableViewController
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

灵活轻便的Table框架1.1.2正式版,适合复杂样式的内容排版,丰富的元素相关API

前言

TableView是在项目开发的时候经常用到的组件,几乎百分之八十以上的页面都需要使用,一个最基本的Table需要实现DataSource的协议才能成功展示;那么当页面越来越多,根据不同的业务场景就需要实现不同的协议,将会出现不少相似冗余代码;当需求改变后,某些复杂页面的排版和业务需求耦合在一起,后期将变得越来越难以维护;大部分情况下,Table需要和下拉刷新上拉加载控件配合使用模拟网络请求;为了满足项目的可维护性,将UI排版和业务需求剥离出来,且自带一些常用的功能,GYTableViewController系列应运而生。<br/>

技术特点

  • 无需继承自定义类,引入头文件UIViewController+GYTableView.h即可使用<br/>
  • 支持OC和Swift(混合)<br/>
  • Section和Cell层次更加清晰,根据传入的Section数据结构内部已经全部实现Section和Cell相关delegate方法<br/>
  • Cell实例可获得外部动态数据,索引位置,上下关系,选中状态等,随时更换样式<br/>
  • 自带MJRefresh框架,提供下拉刷新和上拉加载功能<br/>
  • 提供Section,Cell间距设置,提供选中行高亮、选中行自动居中,提供设置Cell动态高度设置等API<br/>
  • 框架中的元素全部继承于原生的tableView,除部分代理方法外,其他原生方法扔然可以使用<br/>

安装方法

  • pod安装: pod 'GYTableViewController'
  • 手动安装:手动安装需要添加两个库,将GYTableViewController项目文件中Framework文件下的文件导入自身项目,同时此框架基于MJRefresh,所以也需要导入MJRefresh框架文件,手动或者pod都可以,<a href="https://github.com/CoderMJLee/MJRefresh/#How_to_use_MJRefresh" target="_blank">MJRefresh安装方法请戳</a><br/>
  • demo项目图标基于iconfont技术栈,<a href="https://www.iconfont.cn/heslp/detail?spm=a313x.7781069.1998910419.d8d11a391&helptype=code" target="_blank">请戳这里</a><br/>

框架用法

请使用该框架中的元素来代替原生Table控件,对应关系如下:<br/>

UIViewController+GYTableView -> UIViewController
GYTableBaseView -> UITableView
GYTableViewCell -> UITableViewCell
GYTableViewSection 原生使用UIView展示section内容,这里使用GYTableViewSection
SectionNode 用来设置Section样式与GYTableViewSection实例绑定
CellNode 用来设置Cell样式与GYTableViewCell实例绑定

使用时有Table控件的界面直接引入头文件UIViewController+GYTableView.h即可,.h示例如下

  • Objective-C
#import "UIViewController+GYTableView.h"
@interface YourViewController : UIViewController

swift项目在Bridging_Header桥接文件中引入UIViewController+GYTableView.h,参照demo示例<br/>

.m或swift实现文件必须开启gy_useTableView开关来使用Table控件GYTableView

  • Objective-C
- (BOOL)gy_useTableView {
    return YES;
}
  • Swift
override func gy_useTableView() -> Bool {
    return true
}

.m或swift文件中重写headerRefresh添加元素,当自带的下拉刷新控件下拉时调用;从而开始Table内容层次搭建,以及各种类型的Cell位置如何摆放等

- (void)headerRefresh:(GYTableBaseView *)tableView {
    //下拉刷新后开始请求后台提供数据,请求到数据后根据解析的内容展开cell实例和位置等操作,代码结构如下(伪代码)
    request {
        tableView {
            sectionNode {
                cellNode,
                cellNode,
                ...
            }
            sectionNode {
                cellNode,
                ...
            }
            ...
        }
        [tableView headerEndRefresh:YES];//界面搭建完毕后停止刷新
    }
}

Cell控件直接继承GYTableViewCell,.h示例如下

  • Objective-C
#import "GYTableViewCell.h"
@interface YourViewCell : GYTableViewCell
  • Swift
class YourViewCell: GYTableViewCell

.m文件中重写showSubviews方法进行布局,利用getCellData获取Table控件中传入的数据

  • Objective-C
- (void)showSubviews {
    id yourData = [self getCellData];//先获取外部传入的数据
    //开始界面布局...
}
  • Swift
override func showSubviews() {
    let yourData = self.getData()
    //开始界面布局...
}

<a name="添加cell"></a>

添加Cell

Table控制器内部实现

  • Objective-C
- (void)headerRefresh:(GYTableBaseView *)tableView {
    [tableView addSectionNode:[SectionNode initWithParams:^(SectionNode *sNode) {
        //添加一个高度为230,类型为BannerViewCell,展示banner图片序列的Cell
        [sNode addCellNode:[CellNode initWithParams:230 cellClass:RefreshBannerViewCell.class cellData:Mock.bannerUrlGroup]];
    }]];
    [tableView headerEndRefresh:YES];//不要忘了结束刷新,否则刷新动画会停留原地
}
  • Swift
override func headerRefresh(_ tableView: GYTableBaseView!) {
    tableView.add(SectionNode.initWithParams({ sNode in
        //添加一个高度为230,类型为BannerViewCell,展示banner图片序列的Cell
        sNode?.add(CellNode.initWithParams(230, cellClass: RefreshBannerViewCell.self, cellData: Mock.bannerUrlGroup))
    }))
    tableView.headerEndRefresh(true)
}

案例1-1

<a name="批量添加cell"></a>

批量添加Cell

Table控制器内部实现(暴力添加,Swift略过...)

- (void)headerRefresh:(GYTableBaseView *)tableView {
    [tableView addSectionNode:[SectionNode initWithParams:^(SectionNode *sNode) {
        //添加一个高度为230,类型为BannerViewCell,展示banner图片序列的Cell
        [sNode addCellNode:[CellNode initWithParams:230 cellClass:RefreshBannerViewCell.class cellData:self.bannerUrlGroup]];
    }]];
    //注意banner和基金产品列表属于不同区域,应存放到各自section中添加,管理section视图会比较方便
    [tableView addSectionNode:[SectionNode initWithParams:^(SectionNode *sNode) {
        //添加多个高度为80,类型为RefreshFundViewCell,展示基金信息的Cell
        [sNode addCellNode:[CellNode initWithParams:80 cellClass:RefreshFundViewCell.class cellData:self.fundModels[0]]];
        [sNode addCellNode:[CellNode initWithParams:80 cellClass:RefreshFundViewCell.class cellData:self.fundModels[1]]];
        [sNode addCellNode:[CellNode initWithParams:80 cellClass:RefreshFundViewCell.class cellData:self.fundModels[2]]];
        //...
    }]];
    tableView.headerEndRefresh(true);//不要忘了结束刷新,否则刷新动画会停留原地
}

相同类型的Cell添加可以修改成通过原数组批量添加

  • Objective-C
[tableView addSectionNode:[SectionNode initWithParams:^(SectionNode *sNode) {
    //添加多个高度为80,类型为RefreshFundViewCell,展示基金信息的Cell
    [sNode addCellNodeByList:[CellNode dividingCellNodeBySourceArray:80 cellClass:RefreshFundViewCell.class sourceArray:Mock.fundModels]];
}]];
  • Swift
tableView.add(SectionNode.initWithParams({ sNode in
    sNode?.addCellNode(byList: CellNode.dividingCellNode(bySourceArray: 80, cellClass: RefreshFundViewCell.self, sourceArray: Mock.fundNewModels))
}))

案例1-2

<a name="添加section"></a>

添加Section

如果一节内容需要添加section页眉视图,只要在sectionNode实例设置sectionHeaderClass即可,同理section页脚设置sectionFooterClass

  • Objective-C
- (void)headerRefresh:(GYTableBaseView *)tableView {
    [tableView addSectionNode:[SectionNode initWithParams:36 sectionHeaderClass:RefreshFundViewSection.class sectionHeaderData:@"精品专区" nextBlock:^(SectionNode *sNode) {
        //添加section内的cell...
    }]];
    [tableView headerEndRefresh:YES];
}
  • Swift
override func headerRefresh(_ tableView: GYTableBaseView!) {
    tableView.add(SectionNode.initWithParams(36, sectionHeaderClass: RefreshFundViewSection.self, sectionHeaderData: "精品专区", nextBlock: { sNode in
        //添加section内的cell...
    }))
}

分类结构如下

静态图 <br/> 案例1-3

<a name="isunique唯一性"></a>

isUnique唯一性

默认所有相同Class的Cell实例都是相互复用,每次下拉刷新或者table设置reloadData,被复用的Cell实例都会重新触发刷新调用showSubviews,从而根据传递的data展开;然而,一些特殊的Cell不需要复用或只实例化一次,比如标签按钮区域的Cell或者banner区域的Cell,每次下拉都是只用这个实例,可以设置为isUnique作为唯一Cell实例优化提高性能

  • Objective-C
- (void)headerRefresh:(GYTableBaseView *)tableView endRefreshHandler:(HeaderRefreshHandler)endRefreshHandler {
    [tableView addSectionNode:[SectionNode initWithParams:^(SectionNode *sNode) {
       //添加一个高度为230,类型为BannerViewCell,展示banner图片序列的Cell
        [sNode addCellNode:[CellNode initWithParams:230 cellClass:RefreshBannerViewCell.class cellData:self.bannerUrlGroup isUnique:YES]];
        //添加一个高度为90,类型为RefreshHotViewCell,展示banner图片序列的Cell
        [sNode addCellNode:[CellNode initWithParams:90 cellClass:RefreshHotViewCell.class cellData:self.hotModels isUnique:YES]];
    }]];
    [tableView headerEndRefresh:YES];
}
  • Swift
override func headerRefresh(_ tableView: GYTableBaseView!) {
    tableView.add(SectionNode.initWithParams({ sNode in
        //添加一个高度为230,类型为BannerViewCell,展示banner图片序列的Cell
        sNode?.add(CellNode.initWithParams(230, cellClass: RefreshBannerViewCell.self, cellData: Mock.bannerUrlGroup, isUnique:true))
        //添加一个高度为90,类型为RefreshHotViewCell,展示标签按钮区域的Cell
        sNode?.add(CellNode.initWithParams(90, cellClass: RefreshHotViewCell.self, cellData:Mock.hotModels , isUnique:true))
    }))
    tableView.headerEndRefresh(true)
}

上拉加载更多

Table控制器内部设置显示上拉加载控制器

  • Objective-C
- (BOOL)gy_useLoadMoreFooter {
    return YES;
}
  • Swift
override func gy_useLoadMoreFooter() -> Bool {
    return true
}

Table控制器内部重写footerLoadMore

  • Objective-C
//lastSectionNode:上一节sectionNode数据,即当前Table页最后一节
- (void)footerLoadMore:(GYTableBaseView *)tableView lastSectionNode:(Section *)lastSectionNode {
    [lastSectionNode addCellNodeByList:[CellNode dividingCellNodeBySourceArray:80 cellClass:RefreshFundViewCell.class sourceArray:self.fundNewModels]];//将新增的CellNode实例继续添加到上一节SectionNode实例中
    [tableView footerEndLoadMore:YES];//不要忘了结束上拉加载刷新
}
  • Swift
override func footerLoadMore(_ tableView: GYTableBaseView!, last lastSectionNode: SectionNode!) {
    lastSectionNode.addCellNode(byList: CellNode.dividingCellNode(bySourceArray: 80, cellClass: RefreshFundViewCell.self, sourceArray: Mock.fundNewModels))//将新增的CellNode实例继续添加到上一节SectionNode实例中
    tableView.footerEndLoadMore(true)//不要忘了结束上拉加载刷新
}

根据需求添加到Table页最后一节,或者添加到新的一节数据中,并设置添加上限,业务相关代码swift示例略...

if ([tableView getTotalCellNodeCount] > 30) {//总共超出30条数据不添加数据
    [tableView footerEndLoadMore:NO];//直接结束上拉加载刷新,并显示"已经全部加载完毕"
    return;
}
//根据业务需求的不同,可以继续添加到上一节sectionNode,也可以添加到新的一节sectionNode中
if ([lastSectionNode getCellNodeCount] < 15) {//上一节少于15条继续添加到上一节sectionNode
    [lastSectionNode addCellNodeByList:[CellNode dividingCellNodeBySourceArray:80 cellClass:RefreshFundViewCell.class sourceArray:self.
View on GitHub
GitHub Stars52
CategoryDevelopment
Updated1mo ago
Forks6

Languages

Objective-C

Security Score

100/100

Audited on Feb 4, 2026

No findings