千家信息网

如何使用UITableView

发表于:2025-02-22 作者:千家信息网编辑
千家信息网最后更新 2025年02月22日,这篇文章主要讲解了"如何使用UITableView",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用UITableView"吧!痛点在我们iOS开
千家信息网最后更新 2025年02月22日如何使用UITableView

这篇文章主要讲解了"如何使用UITableView",文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习"如何使用UITableView"吧!

痛点

在我们iOS开发中UITableView几乎是所有App都会使用的一个UI控件,因为业务的需要,我们常常会注册多种Cell,然后在

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

中就会很自然的写出一堆类似这样的代码:

事件处理的代码大概是这样的:

这似乎没有什么问题,代码很干净,逻辑也比较清晰。

但是你维护几个版本之后,或者遇到了一个善变的产品经理。

你会发现,这样的代码维护起来真的很危险,稍微一不注意就出错了,这里用的type作为判断条件可能相较与indexPath要好一点。

如果使用indexPath作为判断条件,如果你的cell顺序有变化,或者有改动,那么你可能至少需要维护以下几个地方:

  1. 你的模型数组

  2. cell dequeue的判断条件

  3. 事件处理的判断条件

  4. 。。。。

维护的东西越多,意味着你出错的概率是越大的。

那有没有什么好的方法处理这类代码?

分析

其实我们仔细想想,无论一个多么复杂的UITableView,与之对应的其实只要一个模型数组。

那么我们如果维护好了模型数组,是不是就维护好了UITableView中所有的cell,这是显而易见的。

如果我们的UITableView中有N种cell样式,那么模型数组中肯定也会有N种模型。

也就是说每种cell与每种模型是一一配对的,常规的模型与cell绑定是如上述的思路。

上述的思路,显然不是我们想要的,维护起来太不便,而且耦合性也比较大。

想一想展示一个UITableView的过程

  1. 发起网络请求

  2. JSON to Model,构造模型数组

  3. 数据填充

大致就是这三步吧。

其实在第二步构造模型数组时,我们是不是就可以确定好UI的样式了?

如果这里想不明白,再看看我们上面的分析,一种cell样式对应着一种模型,那么我们知道了模型,是不是就知道了cell样式

如果你还是不大清楚,那们就进入实战部分

实战

先看这样一个简单的页面,你肯定会说:朋友,你TM在逗我们,这和UITableView有毛关系?

这个界面需要UITableView

没错,这个界面在UIViewController中直接构建就可以了。

请再看下面

是不是感觉都很类似,但是又有很多不同的地方。

方案

  1. 一个一个VC的写。

缺点:

有很多重复代码,而且后期的改动需要维护的地方,做不到高内聚。

  1. 抽象一个父类

    缺点:

    虽然三个VC看似UI上有很多共同之处,但是其中的业务处理完全不同的

  2. 抽象一个UIHelper用于构建UI

    缺点:

    这种方案看似很好了,但是你看如果在一个界面中,如果添加一个或者减少一个控件,又得重新做约束了,这也显然不是我们想要的。

下面看看通过UITableView构建的UI

展示

SignInVC 中的代码:

PasswordSignVC 中的代码:

再看cell的dequeue代码

数据的绑定,全部分散到了每个cell中。

Row.h的代码

#import NS_ASSUME_NONNULL_BEGIN@protocol Updatable @optional- (void)updateViewData:(id)viewData;@end@interface Row : NSObject@property(nonatomic, copy, readonly) NSString *reuseIdentifier;@property(nonatomic, strong, readonly) Class cellClass;@property(nonatomic, strong, readonly) id model;- (instancetype)initWithClass:(Class)cls model:(id)model;- (instancetype)initWithClass:(Class)cls;- (void)updateCell:(UITableViewCell *)cell;@endNS_ASSUME_NONNULL_END

Row.m的代码

@interface Row()@property(nonatomic, strong, readwrite) Class cellClass;@property(nonatomic, strong, readwrite) id model;@end@implementation Row- (instancetype)initWithClass:(Class)cls {    if (self = [self initWithClass:cls model:@""]) {    }    return self;}- (instancetype)initWithClass:(Class)cls model:(id)model {    if (self = [super init]) {        self.cellClass = cls;        self.model = model;    }    return self;}- (void)updateCell:(UITableViewCell *)cell {    if ([cell respondsToSelector:@selector(updateViewData:)]) {        [cell performSelector:@selector(updateViewData:) withObject:self.model];    }}- (NSString *)reuseIdentifier {    return [NSString stringWithFormat:@"%@", self.cellClass];}@end

整个Row的代码不过100行,把所有的处理都内聚在了一起,我们只要维护好模型数组就能很好的管理UITableView

UI是构建完成了,但是我相信其中有两个问题你肯定比较关心
  1. Cell 高度计算

  2. Cell上事件的回调

Cell 高度计算

在iOS8之后UITableView中推出了Self-sizing的功能,所以Cell的高度改变

        UIView *dummyView = [[UIView alloc] init];        dummyView.translatesAutoresizingMaskIntoConstraints = NO;        [self.contentView insertSubview:dummyView belowSubview:self.textField];        [dummyView.topAnchor constraintEqualToAnchor:self.contentView.topAnchor].active = YES;        [dummyView.bottomAnchor constraintEqualToAnchor:self.contentView.bottomAnchor].active = YES;        NSLayoutConstraint *constraint = [dummyView.heightAnchor constraintEqualToConstant:60];        constraint.priority = 999;        constraint.active = YES;

如果你对这块不熟悉,请 跳转。如果你想对Auto Layout有一个提高建议看看 Auto Layout Guide, 如果你想知道systemLayoutSizeFittingSize的作用,请看 深入理解Auto Layout 第一弹

Cell上事件的回调

有人肯定会不屑这里,但是我想说:如果不用block、代理、观察者。

怎么把cell上button的事件回调到VC中(button没有暴露给外部)?

我们先看添加Action的方法

- (void)addTarget:(nullable id)target action:(SEL)action forControlEvents:(UIControlEvents)controlEvents;

这里需要这三个参数:

  • target(action的相应者)

  • action(点击按钮相应的方法)

  • controlEvents(这个一般为UIControlEventTouchUpInside)

只要我们找到了target,把action写到target里这个action绑定是不是就完成了。

target其实就是我们的VC,我们只要把VC传递给Cell即可,但是这样是不是Cell又和VC耦合了啊。这个用block,delegate没什么区别吧!

现在我们需要解决的问题就是找到Cell的VC,大功即可告成。

这是就需要一个重要的概念闪亮登场iOS 响应链(Responder Chain)

这里就不展开了,但是你一定要去了解这个。

响应链可以解决的问题:

  • 扩大相应区域

  • 超出父类视图相应依然可以传递

  • 垮图层传递事件

找到UIViewUIViewController

- (UIViewController *)viewController {    UIResponder *responder = self;    while (![responder isKindOfClass:[UIViewController class]]) {        responder = [responder nextResponder];        if (nil == responder) {            break;        }    }    return (UIViewController *)responder;}

ButtonCell事件绑定代码:

这里我们还是要用一个协议的:

注意

用这个协议主要是方便代码的阅读,而且在Swift中是必须使用协议的,因为编译时找不到这个方法。

可以看到ButtonCell的代码中并没有这样一段代码

@property (nonatomic, weak) id delegate;

或者

@property (nonatomic, strong) void (^buttonAction)(void);

这样我们的ButtonCell不会和VC耦合,修改起来真的很方便

感谢各位的阅读,以上就是"如何使用UITableView"的内容了,经过本文的学习后,相信大家对如何使用UITableView这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是,小编将为大家推送更多相关知识点的文章,欢迎关注!

代码 模型 事件 数组 问题 处理 就是 方法 条件 样式 肯定 地方 思路 界面 缺点 高度 学习 耦合 不同 三个 数据库的安全要保护哪些东西 数据库安全各自的含义是什么 生产安全数据库录入 数据库的安全性及管理 数据库安全策略包含哪些 海淀数据库安全审计系统 建立农村房屋安全信息数据库 易用的数据库客户端支持安全管理 连接数据库失败ssl安全错误 数据库的锁怎样保障安全 服务器的辐射会很大吗 数据库预防死锁的四个方式 数据库逻辑运算符号优先级 网络安全教育班会记录 显示驱动软件开发方向好吗 DCS系统网络安全 英文 数据库中查询结果剩余数量 青岛盈实互联网科技怎么样 内蒙古诚信网络技术服务商家 华为云怎么设置远程服务器 数据库并发控制sql语句 服务器的对象资源管理器 星网锐捷软件开发类职位测评 win服务器ssl 服务器对计算机网络提供资源共享 复制数据库的表数据 sql 九江学院计算机网络技术 熊猫直播服务器流量费多少 开展网络安全知识竞赛简讯 数据库集群nec 江苏网络安全审计工控整机商家 少年西游记服务器可以删除吗 百度时间服务器 杭州crm软件开发机构 亚运网络安全宣言 内蒙古诚信网络技术服务商家 电脑里的命令符是不是就是数据库 电子信息工程学软件开发吗 用什么软件开发asp留言板 2011年最新的网络技术
0