具有可变数量子视图的动态 UITableViewCell 高度

2023-12-14

我有一个UITableViewCell使用从远程源检索的数据动态填充。它具有基于单元格中表示的项目类型的可变数量的子视图。我通过使用动态计算单元格内容的大小NSMutableAttributedStringboundingRectWithSize:方法。我获取返回值并计算combinedHeight存储在a中的变量NSMutableDictionary并与indexPath细胞的。一切正常,但是当我尝试使用字典中的值时heightForRowAtIndexPath:方法,它只使用第一组可见单元格,之后一切都是 0。

My question is how I can dynamically size the cell to contain all of the subviews. I am also adding a custom view to the cell's contentView that is smaller width than the cell so that I can achieve a unique style we are going for. This is the style we are going for.

这是我的代码:

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (areFeedItemsLoaded && feedItems.count > 0 && indexPath.row < feedItems.count)
    {
        CGFloat height = [[_cellHeights objectForKey:[self keyForIndexPath:indexPath]] floatValue];

        return MAX(90, height);
    }
    return 44;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;

    if (areFeedItemsLoaded)
    {
        if (feedItems.count == 0)
        {
            if (indexPath.row == 0)
            {
                cell = [EmptyTableViewCell getBlankCell:tableView];
            }
            else
            {
                EmptyTableViewCell *eCell = [EmptyTableViewCell getEmptyCell:tableView withHeaderText:@"No Recent Activity"];
                [eCell setLinkText:@"Your team's activity on Hudl will appear here." withUrl:nil];
                cell = eCell;
            }
        }
        else if (indexPath.row < feedItems.count)
        {
            FeedItem *item = [feedItems objectAtIndex:indexPath.row];
            cell = [self.tableView dequeueReusableCellWithIdentifier:FeedItemCellIdentifier forIndexPath:indexPath];

            if (cell == nil)
            {
                cell = [[FeedItemTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:FeedItemCellIdentifier];
            }

            cell.clipsToBounds = YES;

            cell.backgroundColor = [UIColor clearColor];

            CGFloat combinedHeight = 8;

            UIView *customContentView = [cell viewWithTag:customContentTagId];

            if (customContentView == nil)
            {
                customContentView = [[UIView alloc] init];
                customContentView.tag = customContentTagId;
                customContentView.backgroundColor = [UIColor colorWithR:100 g:100 b:100 a:1];
                [cell.contentView addSubview:customContentView];
            }

            customContentView.frame = CGRectMake(50, 0, 270, 70);

            UIImageView *userImage = (UIImageView *)[cell viewWithTag:userImageTagId];

            if (userImage == nil)
            {
                userImage = [[UIImageView alloc] init];
                userImage.tag = userImageTagId;
                [customContentView addSubview:userImage];
            }

            userImage.frame = CGRectMake(8, 8, 45, 45);
            userImage.layer.cornerRadius = CGRectGetWidth(userImage.frame) / 2;
            userImage.layer.masksToBounds = YES;

            NSURL *imageUrl = item.imageSourceUrl;
            [userImage setImageWithURL:imageUrl placeholderImage:[UIImage imageNamed:@"default-user.png"]];

            CGFloat minX = CGRectGetMaxX(userImage.frame) + 8;

            UILabel *titleLabel = (UILabel *)[cell viewWithTag:titleTagId];

            if (titleLabel == nil)
            {
                titleLabel = [[UILabel alloc] init];
                titleLabel.numberOfLines = 0;
                titleLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
                titleLabel.font = [UIFont fontWithName:@"Helvetica" size:14];
                titleLabel.lineBreakMode = NSLineBreakByWordWrapping;
                titleLabel.tag = titleTagId;

                [customContentView addSubview:titleLabel];
            }

            NSString *title = [NSString stringWithFormat:@"%@ %@", item.creatorName, item.title];
            NSMutableAttributedString *titleText = [[NSMutableAttributedString alloc] initWithString:title];

            [titleText addAttribute:NSForegroundColorAttributeName value:[UIColor colorWithR:204 g:204 b:204 a:1] range:NSMakeRange(0, title.length - 1)];
            [titleText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica-Bold" size:14] range:NSMakeRange(0, item.creatorName.length)];
            [titleText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica" size:15] range:NSMakeRange(item.creatorName.length + 1, title.length - item.creatorName.length - 1)];

            titleLabel.attributedText = titleText;

            CGFloat width = CGRectGetWidth(customContentView.frame) - (CGRectGetMaxX(userImage.frame) + 8) - 8;

            width = MIN(width, 200);

            CGSize titleSize = [titleText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;

            titleLabel.frame = CGRectMake(minX, CGRectGetMinY(userImage.frame), ceil(titleSize.width), ceil(titleSize.height));

            combinedHeight += ceil(titleSize.height) + 8;

            UIView *thumbnailsView = [cell viewWithTag:thumbnailTagId];
            UILabel *descriptionLabel = (UILabel *)[cell viewWithTag:descriptionTagId];

            if ([item.feedItemType intValue] == PlaylistFI || [item.feedItemType intValue] == PlaylistAndNotesFI)
            {
                if ([item.uris count] > 0)
                {
                    if (thumbnailsView == nil)
                    {
                        thumbnailsView = [[UIView alloc] init];
                        thumbnailsView.tag = thumbnailTagId;
                        [customContentView addSubview:thumbnailsView];
                    }
                    else
                    {
                        for (UIView *view in thumbnailsView.subviews)
                        {
                            [view removeFromSuperview];
                        }
                    }

                    thumbnailsView.frame = CGRectMake(minX, CGRectGetMaxY(titleLabel.frame) + 8, width, 40);

                    combinedHeight += 48;

                    for (int i = 0; i < 3 && i < item.uris.count; i++)
                    {
                        NSURL *url = [item.uris objectAtIndex:i];
                        UIImageView *imageView = [[UIImageView alloc] init];
                        int x = i * 60 + i * 8;
                        imageView.frame = CGRectMake(x, 0, 60, 40);

                        [imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:@"soft-dark-grad.png"]];
                        [thumbnailsView addSubview:imageView];
                    }
                }

                if (descriptionLabel == nil)
                {
                    descriptionLabel = [[UILabel alloc] init];
                    descriptionLabel.tag = descriptionTagId;
                    descriptionLabel.font = [UIFont systemFontOfSize:14];
                    descriptionLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
                    descriptionLabel.numberOfLines = 0;
                    descriptionLabel.lineBreakMode = NSLineBreakByWordWrapping;

                    [customContentView addSubview:descriptionLabel];
                }

                NSMutableAttributedString *descriptionText = [[NSMutableAttributedString alloc] initWithString:item.descriptionText];
                [descriptionText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica" size:14] range:NSMakeRange(0, item.descriptionText.length)];

                descriptionLabel.attributedText = descriptionText;

                CGSize descriptionSize = [descriptionText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;

                descriptionLabel.frame = CGRectMake(minX, CGRectGetMaxY(thumbnailsView.frame) + 8, ceil(descriptionSize.width), ceil(descriptionSize.height));

                combinedHeight += ceil(descriptionSize.height) + 8;
            }
            else
            {
                if (thumbnailsView != nil)
                {
                    [thumbnailsView removeFromSuperview];
                }

                if (descriptionLabel != nil)
                {
                    [descriptionLabel removeFromSuperview];
                }
            }

            UILabel *messageLabel = (UILabel *)[cell viewWithTag:messageTagId];

            if ([item.feedItemType intValue] == MessageFI)
            {
                if (messageLabel == nil)
                {
                    messageLabel = [[UILabel alloc] init];
                    messageLabel.tag = messageTagId;
                    messageLabel.font = [UIFont systemFontOfSize:14];
                    messageLabel.textColor = [UIColor colorWithR:204 g:204 b:204 a:1];
                    messageLabel.numberOfLines = 0;
                    messageLabel.lineBreakMode = NSLineBreakByWordWrapping;

                    [customContentView addSubview:messageLabel];
                }

                NSMutableAttributedString *messageText = [[NSMutableAttributedString alloc] initWithString:item.message];
                [messageText addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"Helvetica" size:14] range:NSMakeRange(0, item.message.length)];

                CGSize messageSize = [messageText boundingRectWithSize:CGSizeMake(width, 10000) options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingUsesFontLeading context:nil].size;

                messageLabel.frame = CGRectMake(minX, CGRectGetMaxY(titleLabel.frame) + 8, ceil(messageSize.width), ceil(messageSize.height));
                messageLabel.attributedText = messageText;

                combinedHeight += ceil(messageSize.height) + 8;
            }
            else
            {
                if (messageLabel != nil)
                {
                    [messageLabel removeFromSuperview];
                }
            }

            if ([item.feedItemType intValue] == PlaylistFI || [item.feedItemType intValue] == PlaylistAndNotesFI ||
                [item.feedItemType intValue] == ArticleFI)
            {
                cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
                cell.selectionStyle = UITableViewCellSelectionStyleBlue;
            }
            else
            {
                cell.accessoryType = UITableViewCellAccessoryNone;
                cell.selectionStyle = UITableViewCellSelectionStyleNone;
            }

            [_cellHeights setObject:@(combinedHeight) forKey:[self keyForIndexPath:indexPath]];

            CGRect frame = customContentView.frame;
            frame.size.height = MAX(70, combinedHeight);
            customContentView.frame = frame;
        }
        else if (!requestFailed)
        {
            cell = [LoadingTableViewCell getLoadingCell:tableView];
        }
        else
        {
            cell = [ErrorTableViewCell getErrorCell:tableView];
        }
    }
    else
    {
        cell = (indexPath.row == 0 || indexPath.row < feedItems.count) ? [EmptyTableViewCell getBlankCell:tableView] : [LoadingTableViewCell getLoadingCell:tableView];
    }
    return cell;
}

- (NSIndexPath *)keyForIndexPath:(NSIndexPath *)indexPath
{
    if ([indexPath class] == [NSIndexPath class]) {
        return indexPath;
    }
    return [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
}

您的代码的问题在于计算高度的顺序。如果您在这两种方法中设置断点,您将看到tableView:heightForRowAtIndexPath:实际上被称为 BEFOREtableView:cellForRowAtIndexPath:。这意味着在设置单元格时计算高度将不起作用(因为高度在设置之前将返回 0)。

这是我的建议:

创建一个UITableViewCell子类化并移动您堆积的所有初始化和设置逻辑tableView:cellForRowAtIndexPath:在那个子类中。

一旦单元格设置了任何可能改变其高度的数据属性,请在内部设置单元格的框架高度,因为您将在下一步中使用它。

然后,为了独立计算高度,请在单元格本身中使用如下所示的方法:

+ (CGFloat)heightForCellWithWithData:// use whatever parameters are usually set on a cell that might affect it's height
{
    static dispatch_once_t once;
    static CustomCellClass *sizingCell; // use your custom cell class here
    dispatch_once(&once, ^{
        sizingCell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"sizingCell"];
    });
    // set cell data properties here
    return sizingCell.frame.size.height;
}

然后要获得高度,您只需执行以下操作:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (areFeedItemsLoaded && feedItems.count > 0 && indexPath.row < feedItems.count)
    {
        return [CustomCellClass heightForCellWithWithData:whateverData];
    }
    return 44;
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

具有可变数量子视图的动态 UITableViewCell 高度 的相关文章

  • 在 Swift 3 中单击和双击 UITableViewCell

    我在 TableView Cell 上有故事板 segue 我用它来在单元格单击中传输到另一个 VCdidSelectRowAt方法 现在我双击了TapGestureRecognizer处理手机上的点击问题 问题是 单击时 segue 正在
  • 适用于 iOS 的 Google Cast SDK 2.3.0 不支持 64 位

    似乎是适用于 iOS 的 Google Cast SDK 2 3 0 版本 https developers google com cast downloads GoogleCastFramework 2 3 0 Release zip停止
  • 自动调整大小完成后如何获取帧大小

    我想知道 如何以及何时 viewDidLoad viewWillAppear viewDidAppear 可以获得自动调整大小以适合其父视图的 UIViews 框架大小 从你的问题中不清楚你为什么想要它 但我想这是为了布局你的子视图 幸运的
  • Swift 数组设置索引值不起作用

    我有一个方法 下面的内容 其中queue2只是一个 Int 我打印了很多东西 看看一切是否都正常 public func cool item Int println item println back queue2 insert item
  • 在界面生成器/故事板中设置 UIButton 图像

    我有一个视图控制器 我在故事板中添加了一个圆形矩形按钮 该应用程序运行良好 我还使用故事板将按钮连接到 segue 我正在尝试为此按钮设置一个自定义图像以用于其开和关状态 我如何访问此按钮并设置其属性 在本例中为开和关图像 这是一个屏幕截图
  • 如何在我的 iOS 项目中添加和执行 .sql 文件?

    我找到了很多关于在 iOS 中使用 SQLite 数据库的教程 但没有找到任何直接引用 sql 文件的内容 谁能告诉我如何将现有的 SQL 数据库链接到我的应用程序 编辑 这是一个 MySQL 转储 我们有一个基于浏览器的抽认卡程序 现在我
  • WebGL iOS 渲染为浮点纹理

    我正在尝试在 iOS Safari 上的 WebGL 中渲染浮点纹理 而不是在本机应用程序中 我已经设法让 iOS 读取手动 例如从 JavaScript 创建的浮点纹理 但是当我创建浮点类型的帧缓冲区并使用 GPU 渲染到其中时 它不起作
  • 如何使用 ZBar 读取器的 scanCrop 属性?

    我正在使用 iPhone 的 ZBar SDK 来扫描条形码 我希望阅读器仅扫描特定的矩形而不是整个视图 为此需要将阅读器的 scanCrop 属性设置为所需的矩形 我很难理解必须设置的矩形参数 有人可以告诉我如果在纵向视图上它的坐标是 我
  • 从 Core Data、iOS 获取最后插入的项目

    有没有办法获取核心数据数据库中最后插入的项目 这将返回最后插入的对象 setFetchLimit 1 和 setFetchOffset 所有条目数 1
  • 为了支持 iPhone 5 的更长屏幕,需要检查什么? [复制]

    这个问题在这里已经有答案了 可能的重复 iPhone 5屏幕尺寸如何处理 https stackoverflow com questions 12396545 how to deal with iphone 5 screen size iP
  • swift 中的负数模

    负数模如何在 swift 中工作 当我执行 1 3 时 它给出 1 但余数是 2 其中有什么问题 雨燕余数运算符 计算余数 整数除法 a b a a b b where 是截断整数除法 在你的情况下 1 3 1 1 3 3 1 0 3 1
  • iPad 3 中配备 Xcode 4.2 和 Retina 的 iOS 5.1

    我有一台装有 Mac OS X Snow Leopard 的 Mac 我可以添加 iOS 5 1 吗 使用 iPad 3 的新分辨率 我们将如何处理图像 因为如果该应用程序将在 iPhone 3GS 4 和 iPad 3 中运行 我认为我们
  • 在WKWebview中设置useragent

    如何在 WKWebView 中设置自定义用户代理字符串 我正在尝试嵌入我的应用程序的版本 以便我的服务器端可以看到可用的功能 我找到了以下方法 let userAgent MyApp 1 33 7 request setValue user
  • 打印附加结构(swift 4)

    我有三个 textifled 用于将数据附加到结构中 如何打印我附加的内容 现在我收到一条错误消息 import UIKit class ViewController UIViewController IBOutlet var c UITe
  • iPhone SDK - 在后台线程中运行重复进程

    我有一个iPhone我想在其中每隔一段时间在后台执行一个方法的应用程序1第二 所以在我的主线程中 我有以下代码UIViewController viewDidLoad NSTimer timerWithTimeInterval 1 0 ta
  • Cognito/IAM 策略和 S3 获取对象

    我正在尝试将 S3 和 Cognito 集成到我的 iOS 应用程序中 但到目前为止尚未成功 我相信该错误与我针对 Auth 和 Unauth 用户的 IAM 策略有关 所以这是我的政策 Version 2012 10 17 Stateme
  • 应用未能及时恢复

    我在一个非常具体的场景中遇到 未能及时恢复 崩溃 我认为与看门狗相关 仅在从后台恢复时 并且仅在进入后台后在很短的时间内执行此操作 a最多几秒钟 这似乎是相关的崩溃日志 Incident Identifier E30F2238 5B15 4
  • iOS 发送 iMessage 尽可能简单

    我希望能够以编程方式发送 iMessage 除了调用一个将文本发送到带有消息的号码的函数之外 无需执行任何其他操作 这两个消息都是文本框 我真的很感激一些示例代码 因为我在网上搜索过 但我发现没有任何帮助 这不适用于商业应用程序 仅适用于我
  • iOS 对 Google 云消息传递的支持

    我在谷歌的开发者控制台中看到 GCM 允许为 iOS 生成 API 密钥 我在网上搜索了有关如何在 iOS 应用程序中通过 GCM 实现推送通知的任何类型的文档 但没有找到答案 真的有可能在 iOS 应用程序中使用 GCM 实现推送通知 j
  • 当设置 setVisibleXRangeMaximum 时,iOS-Charts X 轴值无限重复

    我正在尝试绘制一个图表 其中 x 轴是TimeIntervalY 轴是power consumption 由于每天都会有数据 因此将有太多数据无法显示 因此 我想一次显示 5 个值 我通过设置实现了这一点self chart setVisi

随机推荐

  • 如何从WPF中的BackgroundWorker线程直接访问UI线程?

    我正在 WPF 中创建一个备份实用程序 并且有一个关于线程的一般问题 在方法中后台Worker DoWork 语句 Message2 Text 给出错误 调用线程无法访问该对象 因为另一个线程拥有它 我是否无法直接访问backgroundW
  • 如何使用 ctypes 和基于 ctypes 的枚举正确调用以“自定义枚举”作为参数的函数?

    我真的希望一些 Python Ctypes C 专家可以帮助我解决这个问题 这可能是我在使用 Python 与 C 库交互时缺乏正确使用 Ctypes 的类型结构知识 客观的 我需要访问一些库函数 使用 ctypes 加载 DLL 并与之交
  • Angular 中 angular.copy 的替代品是什么

    如何在 Angular 中复制对象并丢失其引用 有了 AngularJS 我可以使用angular copy object 但我在 Angular 中使用它时遇到一些错误 异常 参考错误 angular没有定义 假设你使用的是 ES6 你可
  • Android:可点击 TextView 中的 ClickableSpan

    我有一个可以包含可点击链接的文本视图 当单击其中一个链接时 我想开始一项活动 这工作正常 但也应该可以单击整个文本视图并启动另一个活动 这就是我当前的解决方案 TextView tv TextView findViewById R id t
  • 使用单击时中断停止 for 循环

    我有一个从 1 到 20 的简单循环 我想做的是通过单击按钮来停止循环 我所做的是 我设置了一个条件 即单击按钮后变量的值stop将更改为 1 这将触发break 但值没有改变 var stop 0 for let i 1 i lt 20
  • Homestead 上 Netbeans 中 Laravel Dusk 的 Xdebug

    在 Laravel Homestead 中 我已经能够使用 Xdebug 进行单元测试 功能测试 浏览器浏览等 但当我尝试使用 Xdebug for Dusk 时 它会挂起 在测试 浏览器文件夹中进行测试 我认为这些问题可能会有所帮助 但我
  • WPF 图像平移约束

    我试图找出如何限制平移 使图像完全保持在其包含边框的范围内 任何这方面的帮助将不胜感激 谢谢
  • 将 UIImage 转换为 Keras 模型的 MLMultiArray

    在 Python 中 我使用 keras 训练了一个图像分类模型 以接收 224 224 3 数组形式的输入并输出预测 1 或 0 当我加载保存模型并将其加载到 xcode 中时 它指出输入必须采用 MLMultiArray 格式 有没有办
  • 不可能向外界隐藏模板的实现(为了保护知识产权)。我对吗?

    我已阅读为什么模板只能在头文件中实现 and 为什么我不能将模板类的定义与其声明分开并将其放入 cpp 文件中 如果我创建模板 那么我还将提供对其的访问权限cpp 文件附加到他们的h files 或者直接将定义写入头文件中 因此 如果我想允
  • 无法更改图例符号 nvd3 气泡图

    在我的 nvd3 气泡图中 每组点都有不同的符号 但图例全部为圆圈 代码是here 我只遇到过这个 showLegend false 它可以隐藏或显示图例 我无法理解如何更改图例中的符号 nvd3 不允许您直接访问图例的内部结构 但是 您可
  • 如何在纵向应用程序中录制横向视频? (斯威夫特 2、iPhone)

    我需要在我的纵向 iPhone 应用程序中录制横向视频 是否可能 或者是否受到任何硬件限制的阻止 使用 AVCaptureVideoPreviewLayer 我能够更改预览方向 但视频仍然以纵向录制 欢迎任何想法 您应该能够将视频录制的方向
  • 如何将 cmake 与 boost asio 结合使用?

    我不明白boost asio在我的 C 程序中使用 cmake 我实际上已经尝试和谷歌搜索了很多小时 但我无法让它工作 我想包括boost asio在我的 Ubuntu 18 04 下的 c 项目中 带有一个 cmake 文件 所以我安装了
  • 如何从 Eclipse 为 javaCV 或 openCV 项目制作可运行的 jar

    我在 eclipse 中有一个 openCV 项目 现在 我试图使其可运行 Jar 但一旦尝试运行该 Jar 就无法启动它 我尝试遵循 https groups google com forum topic javacv ziqKIb7Pg
  • 如何在servlet中通过ajax获取数据?

    我想将页面上的一些数据发送到servlet 所以我写了下面的jquery来做到这一点 我用所有数据构建一个json字符串 并直接将其发送到servlet 但我不知道如何从servlet中的ajax获取全部数据 save click func
  • 优化 Sql Reporting Services 2005 中大报表的 PDF 导出

    首先 我知道运行非常大 长时间运行的报告是一个可怕的想法 我知道 Microsoft 有一条经验法则 规定 SSRS 报告的执行时间不应超过 30 秒 然而 有时 由于遵守州法律等外部力量 巨额报告是首选的祸害 在我的工作地点 我们有一个
  • Perl从命令行执行的问题

    上周我在 WinXP 上用 Strawberry Perl 替换了 ActivePerl 我发现我必须使用以下命令运行我的 Perl 脚本perl myperl pl 否则我只需要运行myperl pl在安装草莓之前 我怎么只能跑myper
  • Python:尝试使用请求发布表单

    我正在尝试使用 Python 和请求库登录网站进行一些抓取 我正在尝试以下操作 这不起作用 import requests headers User Agent Mozilla 5 0 payload username niceuserna
  • Django Forms 模板设计类

    Django Forms 框架非常出色 只需通过以下内容即可呈现整个表单 form as p 对于注册表 将上面的内容转换为 p p
  • 如何使用openjson递归解析JSON字符串

    我有以下 JSON 数据 set json N Book IssueDate 02 15 2019 Detail Type Any Type Author Name Annie Sex Female Chapter Section 1 1
  • 具有可变数量子视图的动态 UITableViewCell 高度

    我有一个UITableViewCell使用从远程源检索的数据动态填充 它具有基于单元格中表示的项目类型的可变数量的子视图 我通过使用动态计算单元格内容的大小NSMutableAttributedString和boundingRectWith