iOS 自定义tableView Cell、高度自适应

2023-05-16

1.xib方式创建
每个cell的显示的内容都是固定的,也就是cell的高度都是相同的

加载数据
有plist文件数据结构如下
在这里插入图片描述
创建数据模型

Product.h
@interface Product : NSObject

@property (nonatomic , copy) NSString *name;
@property (nonatomic , copy) NSString *location;
@property (nonatomic , copy) NSString *count;
@property (nonatomic , copy) NSString *price;
@property (nonatomic , copy) NSString *icon;
- (instancetype)initWithDict:(NSDictionary *)dict;
+ (instancetype)goodsWithDict:(NSDictionary *)dict;
@end

Product.m
@implementation Product
- (instancetype)initWithDict:(NSDictionary *)dict{
    if (self = [super init]) {
        self.name = dict[@"name"];
        self.location = dict[@"location"];
        self.count = dict[@"minproduct"];
        self.price = dict[@"price"];
        self.icon = dict[@"icon"];
//        [self setValuesForKeysWithDictionary:dict];
    }
    return self;
}
+ (instancetype)goodsWithDict:(NSDictionary *)dict{
    return [[self alloc]initWithDict:dict];
}
@end

懒加载数据

PageFirstTableViewController.m
//用来存储所有团购商品的数据
@property (nonatomic , strong) NSMutableArray *goods;

#pragma mark -lazyload
- (NSMutableArray *)goods{
    if (_goods ==nil) {
        NSString *path = [[NSBundle mainBundle]pathForResource:@"dataSource.plist" ofType:nil];
        NSArray *arrayDict = [NSArray arrayWithContentsOfFile:path];
       //字典转模型
        NSMutableArray *arrayModels = [NSMutableArray array];
        for (NSDictionary *dict in arrayDict) {
            Product *model = [Product goodsWithDict:dict];
            [arrayModels addObject:model];
        }
        _goods = arrayModels;
    }
    return _goods;
}

实现数据源协议

通过xib方式实现自定义cell
创建以一个.xib文件。在xib中拖一个UITableViewCell,设置高宽。向UITableViewCell中拖子控件。
在这里插入图片描述
创建一个继承自UITableViewCell的类ProductCell与xib文件的cell相关联。通过拖线的方式将cell的子控件拖线到ProductCell的属性上。

ProductCell.m
@property (weak, nonatomic) IBOutlet UILabel *name;
@property (weak, nonatomic) IBOutlet UILabel *price;
@property (weak, nonatomic) IBOutlet UIImageView *icon;
....

实现数据源协议

PageFirstTableViewController.m
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.goods.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    //1.获取模型数据
    Product *model = self.goods[indexPath.row];
    //2.创建单元格
    //通过xib创建单元格
    //由于此方法调用十分频繁,cell的标示声明成静态变量有利于性能优化
    static NSString *ID = @"goods_cell"; //要在xib中设置这个id
    ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        //加载xib文件,loadNibName:方法返回的是一个数组,因为xib中可能有不止一个控件
        cell = [[[NSBundle mainBundle]loadNibNamed:@"ProductCell" owner:nil options:nil] firstObject];//不能加xib后缀
    }
    //3.把模型数据设置给单元格
    cell.name.text = model.name;
    cell.price.text = [NSString stringWithFormat:@"¥%@", model.price];
    cell.icon.image = [UIImage imageNamed: model.icon];
   ...赋值,略
    //4.返回单元格
    return cell;
}

在控制器中直接为cell重的每个子控件赋值数据造成的问题:
1.控制器强依赖于cell,一旦cell内部子控件发生了变化,那么控制器中的代码也得改(紧耦合)。控制器完全依赖于单元格里面的属性。
2.cell的封装不够完整,凡是用到cell的地方,每次都要编写为cell的子控件依次赋值的语句,比如:cell.xxx = model.xxx。如果有10个控制器,每个控制器里都需要用到单元格进行赋值,如果一个单元格里有10个子控件,那么上面这样的代码就要写10次。

对自定义cell进行封装,把模型数据设置给单元格,形如:cell.goods = model;由cell对象内部自己来解析模型数据,并把数据设置到对应的子控件中。在cell中创建一个模型类型的属性,重写该属性的set方法,在set方法中将数据赋值给控件。

ProductCell.h
#import "Product.h"
@interface ProductCell : UITableViewCell
@property (nonatomic , strong) Product *goods;
//封装一个创建自定义cell的方法
+ (instancetype)productCellWithTableView:(UITableView *)tableView;
@end

ProductCell.m
//重写set方法
- (void)setGoods:(Product *)goods{
    _goods =goods;
    self.name.text = goods.name;
    self.price.text = [NSString stringWithFormat:@"¥%@",goods.price];
    self.icon.image = [UIImage imageNamed:goods.icon];
    self.location.text = goods.location;
    self.count.text = [NSString stringWithFormat:@"最低批发量:%@",goods.count];
}
+ (instancetype)productCellWithTableView:(UITableView *)tableView{
    static NSString *ID = @"goods_cell";
    ProductCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
    if (cell == nil) {
        cell = [[[NSBundle mainBundle]loadNibNamed:@"ProductCell" owner:nil options:nil] firstObject];//不能加xib后缀
    }
    return cell;
}

修改后的数据源方法

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    Product *model = self.goods[indexPath.row];
    ProductCell *cell = [ProductCell productCellWithTableView:tableView];
    cell.goods = model;
    return cell;
}

注意:要设置tableView.rowHeight = xib中的cell的高度。不然会报警告
2.纯代码方式创建(frameLayout,自适应高度)
每个cell显示的内容不固定,cell的高度需要根据内容的多少自适应高度(例如微博,朋友圈):
iOS开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
使用纯代码自定义一个tableview的步骤
1.新建一个继承自UITableViewCell的类
2.重写initWithStyle:reuseIdentifier:方法
添加所有需要显示的子控件(不需要设置子控件的数据和frame, 子控件要添加到contentView中)
进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)
3.提供2个模型
数据模型: 存放文字数据\图片数据
frame模型: 存放数据模型\所有子控件的frame\cell的高度
4.cell拥有一个frame模型(不要直接拥有数据模型)
5.重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
6.frame模型数据的初始化已经采取懒加载的方式(每一个cell对应的frame模型数据只加载一次)

原文例子里自定义cell自适应高度是通过加减乘除运算来计算出来的,没有使用autolayout

结合链接原文里面的例子,讲一下自己的个人理解。

步骤2:NJWeiboCell.m文件,在重写的initWithStyle:reuseIdentifier:方法里创建并添加子控件到contentView上,注意创建的子控件属性要声明为weak。另外,像微博vip皇冠图标这种固定的内容的控件,进行一次性数据设置即可。

步骤3、4:除了数据模型(NJWeibo.m)以外还需要frame模型,自定义cell持有frame模型,frame模型持有数据模型。
为什么还需要frame模型?如果没有frame模型,那么自定义cell中直接持有数据模型,即- (void)setWeiboFrame:(NJWeiboFrame *)weiboFrame替换为- (void)setWeibo:(NJWeibo *)weibo,然后在- (void)settingFrame方法中详细设置控件frame,得出cell的高度。每个cell的高度是随子控件内容而变化的。
但是在tableView中,- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath设置行高的代理方法要比- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法先调用。如果没有提供frame模型,那么要直到执行数据源方法,把模型数据设置给单元格(形如:cell.weibo = model;)时,才能获取得到cell的行高。
如果独立出frame模型,就可以在frame模型中详细设置控件frame,得出cell高度,然后在设置行高的代理方法中取出对应的frame模型中的行高。

获取文本lable的宽和高:- (CGRect)boundingRectWithSize:(CGSize)size options:(NSStringDrawingOptions)options attributes:(NSDictionary *)attributes context:(NSStringDrawingContext *)context ;参数1是计算大小的指定范围;如果将来计算的文字的范围超出了指定的范围,返回的就是指定的范围;如果没有超出那么返回的就是真实的范围;不限制范围的话设置CGSizeMake(MAXFLOAT, MAXFLOAT)就可以了。要注意的是:如果是获取多行文本的话,在此之前需要设置文本控件的numberOfLines属性为0。

另外,如果是获取单行文本的size :可以用sizeWithAttributes:方法

更新:使用xib创建自适应高度的tableViewCell
UITableViewCell高度自适应探索这篇文章写得挺细致的,没有其他要补充,大致上和用代码创建自适应高度cell的实现原理上是一样的。比起使用frameLayout创建cell要简单一点,不需要另外设置frame模型来存放所有子控件的frame、cell的高度。

现在有个第三方框架可以很方便地创建高度自适应的tableView cell:

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

iOS 自定义tableView Cell、高度自适应 的相关文章

  • iOS 7 上 Safari 浏览器的用户代理

    我只想在带有 Safari 浏览器的 iPhone 和 iPod 中打开我的网站 对于 Chrome Dolphin 等任何其他浏览器 它不应该打开 但目前我从几乎所有设备获得相同的用户代理 对于Safari User Agent Stri
  • ReactiveCocoa 将 SignalProducers 合二为一

    我正在使用 ReactiveCocoa 并且我有几个 SignalProducers let center NSNotificationCenter defaultCenter let signalProducer1 center rac
  • Objective-C 中发送给对象的消息可以被监听或者打印出来吗? [复制]

    这个问题在这里已经有答案了 可能的重复 Objective C 中拦截方法调用 https stackoverflow com questions 1618474 intercept method call in objective c 如
  • 叠加 SKScene 未显示

    我正在尝试将 SKScene 覆盖在 SCNScene 上 当我在模拟器和 iPhone6 上运行我的应用程序时 overlayScene SKScene 按预期显示 但是当我尝试在 iPhone5 上运行它 尝试了 2 个不同的设备 时
  • 如何在 UICollectionView 中将行居中?

    我有一个UICollectionView与随机细胞 有什么方法可以让我将行居中吗 默认情况下它是这样的 x x x x x x x x x x x x x x 这是所需的布局 x x x x x x x x x x x x 我必须做这样的事
  • 模态转场需要点击 2 次而不是 1 次

    我的 UITableView 需要点击 2 次才能显示所选单元格的详细信息页面 一次用于选择 另一次用于显示详细信息视图 我希望有一个 CLI 直接显示所单击单元格的详细视图 我在 UITableViewManager m 中使用此方法的模
  • ios - 如何声明静态变量? [复制]

    这个问题在这里已经有答案了 C 中声明的静态变量如下 private const string Host http 80dfgf7c22634nbbfb82339d46 cloudapp net private const string S
  • 更改 NSMutableAttributedString 中链接的颜色

    我有以下代码 但我的链接始终是蓝色的 我如何改变它们的颜色 string addAttribute NSLinkAttributeName value tag range NSMakeRange position length string
  • 如何在javascript中计算日出和日落?

    我正在使用appcelerator titan开发一个IOS应用程序 我想让我的应用程序在日出和日落时向用户发送本地通知 解决这个问题的一个好工具是使用 YQL 的雅虎天气 但是 雅虎天气仅供非商业用途 我正在尝试找到一个javascrip
  • 核心数据executeFetchRequest消耗大量内存

    我正在核心数据数据库中插入 cca 100 000 条记录 数据库包含 3 个实体 球员 俱乐部 球员俱乐部 实体之间存在关系 玩家 gt 玩家俱乐部俱乐部 在 PlayerClub 中插入时 我注意到插入大约 50 000 条记录后会消耗
  • 尽早检测有问题的 XIB 视图

    我的笔尖名称有一个拼写错误 当我推向导航控制器时 它在代码中被破坏了 弄清楚它并没有花太长时间 但我认为最好尽早断言格式良好 以便更容易弄清楚 问题是它不是零 它只是无法从笔尖正确地形成自己 在 initWithNib 之后是否有更好的断言
  • ios GPUImage,小尺寸图像处理效果不好?

    我正在尝试为 OCR 准备图像 我使用 GPUImage 来完成 代码工作正常 直到我裁剪图像 裁剪后我得到了糟糕的结果 作物面积 https www dropbox com s e3mlp25sl6m55yk IMG 0709 PNG h
  • 如何将 RGB 值转换为十六进制字符串 iOS swift

    我想将 RGB 值转换为十六进制字符串 我将十六进制转换为 RGB 如下所示 但反之亦然 func hexStringToRGB hexString String gt red CGFloat green CGFloat blue CGFl
  • 我的 iPhone 6 获取 iPhone 5 媒体查询

    我不明白这里发生了什么事 我在 CSS 媒体查询中专门针对 iphone 5 media only screen and min device width 320px and max device width 568px some div
  • 从应用程序打开/关闭 iPhone 的 Wifi

    我需要打开或关闭 iPhone 中的 wifi 有什么方法可以做到吗 还是被禁止了 私有框架 所有使用公共 SDK 编写的应用程序都经过沙箱处理 他们只能访问苹果认为可以在该沙箱中使用的属性和数据 恐怕 Wi fi 不在列表中 请看一下这个
  • Xcode 7.2 无法连接到装有 iOS 9.2 的 iPhone

    出于开发目的 我已经在我的 iPhone 5s 上安装了 iOS 9 2 beta 当然 我还安装了Xcode 7 2 beta 当我想在设备上运行应用程序扩展 键盘 时 该应用程序会正确构建 安装在 iPhone 上并启动 然而 然后我在
  • Swift 字典映射 - 闭包中的 init

    我有 Swift 字典 private var params String AnyObject 这包含查询项目 例如 lat 40 lon 100 我想将这本词典映射到NSURLQueryItem大批 我想让它 迅速 params map
  • iOS 版 Google 地图 sdk 中折线的轮廓

    我的要求是在地图上显示一条绿色折线 但当地图切换到卫星视图时 绿色折线变得不清楚 我无法改变折线的颜色 因此 为了将折线与背景 地图的卫星视图 区分开来 我需要为折线绘制白色轮廓 我浏览了 GMSPolyline 类的文档 但找不到任何可以
  • 为什么我收到 com.facebook.sdk.login 错误 308?

    我正在使用 Xcode 7 0 在 iOS 9 0 2 上进行测试并使用 Facebook SDK 4 7 0 当我登录用户时 大多数时候一切都正常 但有时我不断收到此错误 但我不知道为什么 操作无法完成 com facebook sdk
  • 如何在 Swift 中将所有 iOS 设备的标签水平居中

    我不知道如何使标签在图像视图中水平居中 标签说 You ve been here What would you rate us 我想要What would you rate us属于 You ve been here 我试图完成此操作的方法

随机推荐

  • Kotlin Native Konan 默认依赖路径修改

    记录一下 C User xxxx konan是kotlin native依赖下载的默认缓存路径 kotlin native 文件夹下的配置文件 找到konan properties文件 发现一段注释使用 KONAN DATA DIR 环境变
  • 官方控件SwipeRefreshLayout内嵌套滑动控件会导致进度条指示器空白并保留

    前言 xff1a 准备实现一个刷新获取数据的功能 刷新的时候遇到了空白圈圈保留 xff0c 于是开始查看SwipeRefreshLayout的源码并想了好几种方式去修复 xff0c 最终采用反射 xff08 第一次使用反射可能用的很糟糕 x
  • NestedScrollView向上滚动一段距离

    注 xff1a 记一次问题 xff08 花了三个小时 xff09 尝试给控件设置焦点 没效果 问题复现 AppBarLayout 43 NestedScrollView 并给NestedScrollView设置以下代码 xff09 lt a
  • day65 JavaWeb框架阶段——全文检索技术Lucene(非结构化数据查询方法,中文分析器IKAnalyzer)

    1 今日内容 什么是全文检索 xff0c 如何实现全文检索Lucene实现全文检索的流程 a 创建索引 b 查询索引配置开发环境入门程序分析器的分析过程 a 测试分析器的分词效果 b 第三方中文分析器索引库维护 a 添加文档 b 删除文档
  • 【已解决】阿里云配置安全组后,仍无法访问端口问题

    文章首发于如下链接 xff1a http 80sdianying xyz id 61 8 最近在搭python的falsk服务器 xff0c 遇到一个问题 xff0c 在服务器运行python程序后 xff0c 外网无法访问到该程序 xff
  • ubuntu 14.04 软件中心闪退解决方案

    ubuntu 14 04 软件中心闪退解决方案 参考文章 xff1a xff08 1 xff09 ubuntu 14 04 软件中心闪退解决方案 xff08 2 xff09 https www cnblogs com lvchaoshun
  • “No X11 DISPLAY variable was set”问题的解决过程

    No X11 DISPLAY variable was set 问题的解决过程 参考文章 xff1a xff08 1 xff09 No X11 DISPLAY variable was set 问题的解决过程 xff08 2 xff09 h
  • postgreSql查询复杂json数组字段

    因为在生产环境中使用到两次 故而记录一下对复杂json字段提取字段值的SQL 先看数据格式 xff1a 假设表名为 ry xff1b 下面的数据格式是我们的字段ryxx 34 bh 34 34 123 34 34 jbxx 34 34 xm
  • VS调用大恒相机sdk实时显示图像并进行图像处理+OPENCV

    前言 xff1a 近期企业需要用大恒相机的sdk开发项目 xff0c 我采用VS2017 43 QT5 10 1 43 MSVC 一 环境配置 VS2017和qt的安装不多介绍 xff0c 主要介绍大恒sdk的配置 1 https www
  • 元学习 每日学习之路

    参考视频 2 21 元学习 xff1a 学会如何去学习 xff0c 就是带着这种对人类这种 学习能力 的期望诞生的 Meta Learning希望使得模型获取一种 学会学习 的能力 xff0c 使其可以在获取已有 知识 的基础上快速学习新的
  • 笔记本电脑连接WIFI速度很慢-解决办法 亲测有效【5MB/S直达10MB/S】

    电脑连接WIFI 经常发生连续断网 xff0c 或者家里的网明明是100M 但是连接电脑WIFI 却连50M都不到 于是在网上查了很多资料 xff0c 网上大多的方法 我讲两个 xff1a 一 用电脑管家 xff0c 360 xff0c 鲁
  • react-native 调用Settings.Secure.getstring获取了android_id / app上架违规获取android_id被拒

    华为上架时 被违规获取android id原因拒绝上架 使用HookLoginDemo检测结果如下 span class token number 2022 span span class token operator span span
  • Linux——网络桥接

    什么是网络桥接 xff1f 在网络的使用中 xff0c 有时需要搭建网络桥来实现网络桥接 例如在一台主机上制作一台虚拟机 xff0c 虚拟机是没有物理网卡的 xff0c 这时虚拟机数据的发送和接收就需要通过主机上的物理网卡 xff0c 需要
  • STM32实战之LED循环点亮

    接着上一章讲 本章我们来讲一讲LED流水灯 xff0c 循环点亮LED 在LED章节有的可能没有讲到 xff0c 本章会对其进行说明 xff0c 尽量每个函数说一下作用 也会在最后说一下STM32的寄存器 xff0c 在编程中寄存器是避免不
  • 远程连接桌面到ubuntu登录闪退

    问题 xff1a 远程连接到Ubuntu的时候登录闪退 xff0c 密码正确 xff0c 且之前在本地登录过没有问题 xff0c ssh登录没有问题 原因 xff1a 就是因为之前在本地登录了没有登出 xff0c 只是锁屏了 xff0c 导
  • CSRF跨站请求伪造漏洞修复

    文章目录 一 漏洞描述二 解决建议二 解决方法Springboot 配置文件增加配置编写配置类编写过滤器 提示 xff1a 以下是本篇文章正文内容 xff0c 下面案例可供参考 一 漏洞描述 跨站请求伪造 xff08 Cross site
  • Linux挂载磁盘(扩容)

    磁盘相关介绍 xff1a fdisk l 查看磁盘占用情况 sda xff1a 代表一个磁盘 s SCSI d 磁盘 a 代表挂在在SCSI类型的硬盘的第一块 Linux文件系统 xff1a 都是用文件 形式描述的 SCSI xff1a 用
  • 动规例题C++代码

    动规题目 xff1a 字符串S由小写字母构成 xff0c 长度为n 定义一种操作 xff0c 每次都可以挑选字符串中任意的两个相邻字母进行交换 询问在至多交换m次之后 xff0c 字符串中最多有多少个连续的位置上的字母相同 xff1f 参考
  • Centos7下Samba服务器配置

    环境 vm下centos7 6 xff0c IP地址 xff1a 192 168 139 200 Samba概述 Samba是在Linux和UNIX系统上实现SMB协议的一个免费软件 xff0c 由服务器及客户端程序构成 SMB xff08
  • iOS 自定义tableView Cell、高度自适应

    1 xib方式创建 每个cell的显示的内容都是固定的 xff0c 也就是cell的高度都是相同的 加载数据 有plist文件数据结构如下 创建数据模型 Product span class token punctuation span h