有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?

2023-11-02

Apple 算是最重视应用开发体验的公司了。从Xib到StoryBoard,从Auto Layout到Size Class,每一次的更新,都会给iOS应用的开发带来不小的便利。但是,对于绝对多数iOS攻城狮来说,我们依然还是很害怕写UITabelVIew的自适应布局。当然,害怕不是因为我们不会写,或者本身有什么特殊的技术点,而是因为太麻烦。当然,文章的后半部分,会给出相应的解决方案,毕竟本文不是为了吐槽而吐槽。

UITabelView的自适应布局有多麻烦?

数据类型的不确定性:种类越多,页面越复杂。

pic_001.PNG

网易新闻

以网易新闻的客户端为例,可能的数据包括文字新闻,图片新闻,图集,推广,视频等。每一种数据,又根据来源或点击量等细分出许多不同的状态。基本上每种数据类型,都至少需要一种单独的Cell去呈现,每一个Cell的布局,都要单独去写。所以说,数据的类型将直接决定页面本身的复杂度。

数据长度的不确定性: 不确定字段越多,迭代成本越高。

pic_002.png

新浪微博

上图取自新浪微博。稍微有点经验的iOS攻城狮,都猜到我要吐槽什么了吧!没错,就是同种数据类型,但是内部字段的长度可能不同,而且还要都要给他们显示出来!其实我也很希望自家的应用都像网易那样,固定长度显示新闻,显示不完,就直接截断--可惜那样的应用都是别人公司的应用。可能你会说: 顶部给个非微博正文区域给个固定高度;文字区域动态计算出高度;图片部分,图片高度固定,根据数量动态计算高度;转发部分同理;然后根据数据在tabelView的代理方法 tableView:heightForRowAtIndexPath: 中动态返回高度即可。是的,思路就是这么个思路,但是你确定产品经理一直不会改需求?你确定不需要适配 6plus时,字号要大点?你确定自己的应用不希望大屏上一样能显示更多的图片?你确定老板不是盘算着 iPad版也交给你维护?所以说,对于这种数据长度不确定,但是又要求完全显示的设计,最复杂的不在于实现,而在于后期的迭代。可变字段越多,迭代越复杂。如果连显示方式都改了,那就基本等于重做了几遍。

cell高度计算有坑: 难以理解的诡异问题

在 tableView:heightForRowAtIndexPath: 中计算高度时,是有坑的,对于刚接触iOS的攻城狮来说,几乎是难以理解的诡异问题。这里简单说两个,其他的大家可跟帖补充:

  • 文字高度计算时 0.1 高度误差问题。

cell中经常需要使用 textRectForBounds: limitedToNumberOfLines: 来计算某一个文字的显示高度。这里,其实有一个很大的坑的,如果你没遇到只能说明你很幸运。由于浮点数四舍五入机制的存在,所以偶现UILabel最后一行无法显示的情况。原因也很诡异: 在你计算时,部分值会存在稍许的不超过0。01的误差,大多数情况下,这个误差值,可以安全忽略,但是确实存在那0。01误差刚好是绝对换行与不换行的分界值,因为0。01的误差,可能计算出来的高度就不足以显示最后几个文字。为了安全起见,如果需要计算文本高度,我都是加上一个额外的0。1来保证最后一行肯定可以显示。

  • 手动调用 tableView:cellForRowAtIndexPath: 获取cell,引起的卡顿问题。

这个可能也是一些有经验的开发者也会混淆的问题: 不要在自己的代码中调用 tableView:cellForRowAtIndexPath: 方法来获取某一个位置的 cell,来进行关于这个cell的某些计算,因为你手动调用这个方法产生的cell不会参与cell的复用! 各种缘由,不过多解释,总之结论就是,只要系统自己调用 tableView:cellForRowAtIndexPath: 方法产生的 cell才会参与cell的复用。

关于这个话题,比较易犯的错误是,竟然有开发者在tableView:heightForRowAtIndexPath: 中调用 tableView:cellForRowAtIndexPath: 来获取cell,然后计算cell高度。然后你会发现,凡是稍微涉及到图片显示的界面,你的显示是对的,但是滚动非常卡顿,因为你在自己浑然不觉的情况下创建了N个Cell,而且这些Cell绝对不会参与复用。

为什么我现在不再害怕写UITabelView的自适应布局?

是的,我现在一点也不担心去处理各种UITabelView布局。不是因为我有一股所谓的不畏艰难的伟大工作精神,而是因为我切实找到了解决办法。具体该怎么做呢?

  • 使用AutoLayout 布局你的cell

坦白说,咱都是刚入行的人,使用AutoLayout布局,写一个自适应的Cell,大家估计也都会。可以用xib,也可以用纯代码写。如果准备用纯代码写,建议你先好好研究下 Masonry - 使用纯代码进行iOS应用的autolayout自适应布局

  • 使用 UITableView-FDTemplateLayoutCell 根据单元格内容的约束自适应单元格高度

pic_003.png

博客讨论

坦白说,我原来也是: 虽然cell用着AutoLayout,但是计算cell高度时,也是看着设计图返回一个适合的值--想想都虐心。前天,一个热心的开发者在我博客留言说: 他用 Masonry 进行Cell的高度自适应时遇到了问题。我第一反应是: Masonry 能用来计算cell高度?! 然后,他提到了一个第三方UITableView-FDTemplateLayoutCell,好像是国内的大神写的,具体介绍可以看这里: 优化UITableViewCell高度计算的那些事。这篇文章的博主关于 UITableView-FDTemplateLayoutCell 分析很详尽,用一句总结就是: 一行代码解决cell高度动态计算问题。

  • 一个关于Masonry 和 UITableView-FDTemplateLayoutCell结合使用的小例子

pic_004.png

一个关于Masonry 和 UITableView-FDTemplateLayoutCell结合使用的小例子

示例下载地址: 点击下载

非常感谢 @未来帅哥 的讨论,给了我很大启发和帮助,我也如约做了一个关于Masonry 和 UITableView-FDTemplateLayoutCell结合使用的小例子,以解决他的问题:关于如何让左侧图片底部总是不被遮盖。

核心代码片段:

1
2
3
4
5
6
7
8
9
10
11
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
     
     CGFloat height = [tableView fd_heightForCellWithIdentifier: NSStringFromClass([YFAutoLayoutCell class]) cacheByIndexPath:indexPath configuration:^(YFAutoLayoutCell * cell) {
         YFAutoLayoutCellModel * model = [self.data objectAtIndex: indexPath.row];
         
         cell.model = model;
     }];
     
     return  height;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/**
  *  初始化视图.
  */
- (void) setupView
{
     self.imgView = [[UIImageView alloc] init];
     self.introLabel = [[UILabel alloc] init];
     
     [self.contentView addSubview: self.imgView];
     [self.contentView addSubview: self.introLabel];
     
     self.introLabel.numberOfLines = 0;
     
     [self.imgView makeConstraints:^(MASConstraintMaker *make) {
         make.top.left.equalTo(8);
         make.size.equalTo(CGSizeMake(60, 60));
         make.bottom.lessThanOrEqualTo(-8);  // 这里是关键
     }];
     
     [self.introLabel makeConstraints:^(MASConstraintMaker *make) {
         make.left.equalTo(self.imgView.right).offset(8);
         make.top.equalTo(self.imgView);
         make.right.equalTo(-8);
         make.bottom.equalTo(-8);
     }];
}

小结

有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?因为你还在用传统的方式去计算cell的高度! Auto Layout + UITableView-FDTemplateLayoutCell + Masonry,耐心研究几个小时,绝对让你受益匪浅!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局? 的相关文章

  • NSAttributedString 的 AutoLayout 行高计算错误

    我的应用程序从 API 中提取 HTML 将其转换为NSAttributedString 为了允许可点击的链接 并将其写入自动布局表中的一行 问题是 每当我调用这种类型的单元格时 高度都会被错误计算并且内容会被截断 我尝试了不同的行高计算实
  • 将 .p12 证书存储在钥匙串中以供稍后使用

    我正在尝试按照 Apple 文档处理此处的客户端 p12 证书 https developer apple com library ios documentation Security Conceptual CertKeyTrustProg
  • sizeToFit 运行异常

    我有一段代码 每次发生后端数据库更改时都会执行 本质上我在父视图中有一个标签 标签由许多状态消息之一更新 每个状态消息位于不同的行上 并以换行符 n 结尾 每条状态消息只能在一行上 并且不能过多 我遇到的问题是 当视图首次重新加载时 一切正
  • NSIndexpath.item 与 NSIndexpath.row

    有谁知道之间的区别NSIndexpath row and NSIndexpath item 具体来说 我在以下情况中使用哪一个 UITableViewCell tableView UITableView tableView cellForR
  • SKScene和SKView的paused属性之间的区别

    我使用以下代码暂停 SKScene self paused YES 然而 根据这个answer https stackoverflow com a 21593852 2043580 by 安德烈 戈尔杰耶夫 https stackoverf
  • 在 UITableViewCell 内动态更改标签宽度

    我正在尝试建立一个自定义表格视图 正如您在图片中看到的 我在故事板一侧将标签的宽度默认设置为 160 磅 并在加载表格时动态更改宽度 我通过修改 cellForRowAtIndexPath 委托方法来实现此目的 因此 根据日期的长度 我设置
  • Swift 1.2 可选外部变量?

    由于 Swift 无法访问编译变量 因此我创建了一个指向编译变量的 Objective C extern 变量 编译变量转换器 h extern NSString const NetworkApiBasicAuthUsername 编译变量
  • WKWebView在后台,几个奇怪的断言

    我想找出iOS中当前浏览器的userAgent 所以在 Xcode 创建的默认项目中我添加了 import ViewController h import
  • UINavigationBar 滑开而不是留在原处

    我创建了演示项目来展示问题 我们在 UINavigationController 中有两个视图控制器 MainViewController这是根 class MainViewController UIViewController lazy
  • 如何在 iOS 应用程序中检测所有可用的 Wifi 网络并连接到其中之一

    在我的 iOS 应用程序中 我想检测所有可用的 wifi 网络 然后从列表中选择一个网络并连接到它 目标是不打开应用程序内置的设置来连接 Wi Fi 而是在我的应用程序中完成这一切 首先 这可能吗 如果可能的话 请指出要使用哪些框架和方法
  • 带有图像的 UITableView 滚动非常慢[重复]

    这个问题在这里已经有答案了 可能的重复 带图像的表格视图 加载和滚动缓慢 https stackoverflow com questions 4071497 table view with images slow load and scro
  • UIImageWriteToSavedPhotosAlbum 选择器语法问题

    努力让 UIImageWriteToSavedPhotosAlbum 快速工作https developer apple com library ios documentation UIKit Reference UIKitFunction
  • 旋转 GPUImageTiltShiftFilter - GPUImage

    我想要一个非水平 GPUImageTiltShiftFilter 旋转 我想将其旋转到任意旋转角度 我还希望过滤器速度快 可以通过带有 UIRotationGestureRecongizer 的 UI 进行旋转 我该怎么做呢 啊 想通了 不
  • 在后台继续下载

    我正在创建一个应用程序 其中我从服务器下载一些数据 在后台运行时 我希望连接继续运行 以便可以下载数据 我知道有方法应用程序委托 void applicationDidEnterBackground UIApplication applic
  • iOS Twitter NSURLErrorDomain 代码=-1012

    我正在尝试通过在我的应用程序中注册 Twitter 来获取用户的联系方式 我发现this https github com malcommac DMTwitterOAuthgithub上的项目看起来非常好 我只遇到一个问题 如果我使用来自
  • 在 Swift 中,如何为具有自动布局的 UIView 制作动画,就像页面滑入一样?

    我尝试创建一个 UIView 来表示一个大小与设备屏幕相同的页面 由于该应用程序支持方向 因此我使用 AutoLayout 来构建它 它工作正常 直到我尝试将页面动画化以从右侧滑入 经过一番研究后 我能想到的最好的办法是 myView UI
  • Swift 错误:发出 SIGABRT 信号如何解决

    我只是 Swift 编码的初学者 我的想法很简单 就是一个有两个按钮的应用程序 单击时 文本字段将更改其文本 在 Main StoryBoard 中 我添加一个文本字段和两个按钮 在 ViewController swift 文件中 我这样
  • 使用自定义格式将字符串转换为 NSDate [重复]

    这个问题在这里已经有答案了 可能的重复 NSString 到 NSDate https stackoverflow com questions 1353081 nsstring to nsdate iPhone 如何将 yyyyMMddTh
  • 如何删除以前的 ViewController

    我是一名学生 对编程还很陌生 我正在尝试在业余时间学习 Objective C Swift 我使用 spriteKit 和 swift 制作了一个游戏 有多个菜单 场景 我正在尝试从一个视图控制器转换到另一个视图控制器 为此 我使用了以下代
  • iOS 11 特定设置部分的 URL 方案停止工作

    我的应用程序使用 URL 方案将用户直接带到 设置 常规 关于 部分 以下 URL 在 10 3 x 中工作正常 应用程序首选项 根 常规 路径 关于 然而 这个 URL 方案在 iOS 11 GM 版本中不再有效 它仅启动 设置 应用程序

随机推荐

  • 在Android里显示网页的多种方式

    在Android中显示网页主要有两种方式 一种是在Activity里面直接显示网页 另一种是调用浏览器显示网页 方式不同 使用的方法也不同 下面我们分别讲解 一 在Activity里面直接显示网页 1 在Manifest xml文件里添加I
  • android 功能模块之通讯模块五

    Android通讯录开发之获取运营商号码段 移动 联通 电信 2014年1月8日 开发记录 碎碎念 2014年的第一篇博客 原本是想写一篇随笔来开头 只因自己太懒把这件事忘记了 或者根本就不想写 我当实习生也当了接近半年了 工作上的内容和学
  • LLM总结(持续更新中)

    最新的参见LLM Summary 引言 当前LLM模型火出天际 但是做事还是需要脚踏实地 此文只是日常学习LLM 顺手整理所得 本篇博文更多侧重对话 问答类LLM上 其他方向 代码生成 这里暂不涉及 可以去看综述来了解 之前LLM模型梳理
  • 正态分布与均匀分布之间的变换

    一 任何分布都能化为 0 1 0 1 0 1 均匀分布 假设 F X a p x a F X a p x le a FX a p x a 为累积分布函数 f x f x f x 为概率密度函数 F X a a f x d x F X a i
  • stm32 IAP引导两个APP出现的问题及解决方法

    最近在做bootloader引导app时发现如果APP有操作系统时 会引导不起来 现象如下 平台 stm32H743 采用stm32cubemx配置的HAL库 测试方式 上电后运行boot loader bootloader是裸机运行 由b
  • cmake使用笔记

    vim CMakeLists txt mkdir build cd build cmake 创建 CMakeLists txt 添加内容 cmake minimum required VERSION 3 26 工程名称 project he
  • OSI、TCP/IP模型及协议

    文章目录 OSI模型 TCP IP模型 TCP协议 TCP报文 首部字段 数据字段 三次握手 三次握手时c s的状态 四次挥手 UDP协议 HTTP协议 HTTP 协议下的消息类型 Cookie Session HTTPS 常见web攻击技
  • SpringBoot配置默认Json解析工具以及空值处理方式

    SerializeConfig config new SerializeConfig 设置序列化为下划线 config propertyNamingStrategy PropertyNamingStrategy SnakeCase Stri
  • Android UI架构(十三)--App请求切换帧率(4)之SurfaceFlinger切换帧率.md

    文章目录 参考资料 简述 一 SurfaceFlinger接受帧率变化 1 1 SurfaceFlinger setDesiredActiveConfig 1 2 SurfaceFlinger repaintEverythingForHWC
  • 用C语言编写简化版银行系统:ATM取款机

    1 问题描述 用c语言编写一个简化的银行自动存款系统 适合刚接触C语言 尝试编写100多行代码的初学者作为参考 该代码编写围绕着银行ATM机器的4个业务 分别是查询 取款 存款 修改密码 其中需要两个文件 一个为DrawMoney txt文
  • 阿里巴巴开源限流系统 Sentinel 全解析

    今年下半年阿里开源了自研的限流系统 Sentinel 官方对 Sentinel 的介绍中用到了一系列高大山的名词诸如 限流 熔断降级 流量塑形 系统负载保护等 还有漂亮的形容词诸如 轻巧 专业 实时等 作为技术消费者看到这样的广告词之后禁不
  • 掌握GDB调试工具,轻松排除bug!

    一 什么是GDB gdb是GNU debugger的缩写 是编程调试工具 GDB官网 https www gnu org software gdb GDB适用的编程语言 Ada C C objective c Pascal 等 GDB的工作
  • Python-第三方库requests详解

    Requests 是用Python语言编写 基于 urllib 采用 Apache2 Licensed 开源协议的 HTTP 库 它比 urllib 更加方便 可以节约我们大量的工作 完全满足 HTTP 测试需求 Requests 的哲学是
  • C++中的namespace(using namespace)的详细理解

    在C 语言编写的程序中 变量和函数等的作用范围是有一定限制的 比如 在函数体中定义的一个临时变量就不可以在函数体外使用 为了解决变量和函数等的作用范围 在C 语言中引入了名空间的概念 并增加了关键字namespace和using 在一个名空
  • 《STL源码剖析》(四)——序列式容器

    1 序列式容器 所谓序列式容器 其中的元素都可序 但未必有序 C 本身提供了一个序列式容器array STL另外提供了vector list deque stack queue priority queue等序列式容器 其中stack和qu
  • C++知识总结(内附超详细知识框架图)

    C 知识总结 由于在学习C 的同时博主也在学习Linux系统编程 Linux网络编程以及数据库 所以从开始学习C 到现在结束已经有一年多时间了 C 是博主学习的第一个面向对象的语言 在学习过程中也是逐渐体会到了面向对象编程的种种好处 但C
  • 第十二章 YOLO的部署实战篇(下篇)

    文章目录 前言 专栏概括 1 cuda教程目录 2 cuda教程背景 3 cuda教程内容 一 yolov5部署整体逻辑 1 yolov5的main函数 2 yolo h头文件 3 整体架构显示 二 yolov5模型的onnx转engne代
  • oracle tmp表空间不足,临时表空间不足引起的ORA-01114错误

    数据库程序突遇ORA 01114错误 提示内容如下 错误原因 Select error ORA 01114 将块写入文件 时出现 IO 错误 块 ORA 27069 skgfdisp 尝试在文件范围外执行 I O OSD 04026 无效的
  • Unity + vuforia 开发虚拟按钮

    首先在创建虚拟按钮之前 还是要首先了解imageTarget的创建方式 我自己时参考dzyi的博客弄的 推荐大家 写的很详细 地址 http blog csdn net dzyi article details 22898929 创建虚拟按
  • 有了Auto Layout,为什么你还是害怕写UITabelView的自适应布局?

    Apple 算是最重视应用开发体验的公司了 从Xib到StoryBoard 从Auto Layout到Size Class 每一次的更新 都会给iOS应用的开发带来不小的便利 但是 对于绝对多数iOS攻城狮来说 我们依然还是很害怕写UITa