You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

包含内嵌UITableView的UITableViewCell如何实现动态自适应高度

解决方案
    1. 修正错误配置
      首先删除self.contentView.translatesAutoresizingMaskIntoConstraints = NO;这行代码,系统默认会管理contentView的约束,手动关闭会导致高度计算失效。
    1. 自定义自动高度适配的内部TableView
      创建SPDAutoHeightTableView子类,自动监听contentSize变化更新自身高度:
// SPDAutoHeightTableView.h
@interface SPDAutoHeightTableView : UITableView
@property (nonatomic, copy) void (^onHeightChanged)(CGFloat newHeight);
@end

// SPDAutoHeightTableView.m
@implementation SPDAutoHeightTableView
- (void)setContentSize:(CGSize)contentSize {
    [super setContentSize:contentSize];
    // 内容大小变化时更新高度
    for (NSLayoutConstraint *constraint in self.constraints) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            if (self.onHeightChanged) self.onHeightChanged(contentSize.height);
            break;
        }
    }
    [self invalidateIntrinsicContentSize];
}
- (CGSize)intrinsicContentSize {
    return self.contentSize;
}
@end
    1. 修正Cell内的约束和回调配置
      修改Cell初始化代码,增加高度变更回调,完善table2的约束添加逻辑:
//  Cell.h 中新增回调属性
@property (nonatomic, copy) void (^onCellHeightNeedUpdate)(void);

// Cell.m 实现
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
        self.openSection = -1;
        SPDSpinnerView *spinner = [[SPDSpinnerView alloc] initWithFrame:self.contentView.bounds];
        spinner.label.text = @"Loading...";
        spinner.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
        // 加载视图加在contentView上
        [self.contentView addSubview:spinner];
        
        __weak typeof(self) weakSelf = self;
        [self loadDataWithCompletion:^(BOOL success) {
            __strong typeof(weakSelf) strongSelf = weakSelf;
            // 移除加载动画
            for (UIView *view in strongSelf.contentView.subviews) {
                if ([view isKindOfClass:[SPDSpinnerView class]]) [view removeFromSuperview];
            }
            if (success) {
                // 用自定义的自动高度TableView
                SPDAutoHeightTableView *table2 = [[SPDAutoHeightTableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
                table2.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
                [table2 registerClass:[SPDChangelogHeaderView class] forHeaderFooterViewReuseIdentifier:@"headerView"];
                table2.scrollEnabled = NO;
                table2.delegate = strongSelf;
                table2.dataSource = strongSelf;
                table2.translatesAutoresizingMaskIntoConstraints = NO;
                strongSelf.table2 = table2;
                
                // 高度变化回调
                table2.onHeightChanged = ^(CGFloat newHeight) {
                    if (strongSelf.onCellHeightNeedUpdate) {
                        strongSelf.onCellHeightNeedUpdate();
                    }
                };
                
                [UIView transitionWithView:strongSelf.contentView duration:.25 options:UIViewAnimationOptionTransitionCrossDissolve animations:^{
                    [strongSelf.contentView addSubview:table2];
                    // 加全约束
                    [NSLayoutConstraint activateConstraints:@[
                        table2.topAnchor.constraintEqualToAnchor:strongSelf.contentView.topAnchor,
                        table2.leadingAnchor.constraintEqualToAnchor:strongSelf.contentView.leadingAnchor,
                        table2.trailingAnchor.constraintEqualToAnchor:strongSelf.contentView.trailingAnchor,
                        table2.bottomAnchor.constraintEqualToAnchor:strongSelf.contentView.bottomAnchor,
                        // 初始高度约束,后续会自动更新
                        table2.heightAnchor.constraintEqualToConstant:0
                    ]];
                } completion:^(BOOL finished) {
                    // 添加完成后刷新table2数据触发高度计算
                    [table2 reloadData];
                }];
            } else {
                // 自行添加错误提示Label的约束,避免用系统textLabel导致的布局问题
                UILabel *errorLabel = [[UILabel alloc] init];
                errorLabel.text = @"数据加载失败";
                errorLabel.translatesAutoresizingMaskIntoConstraints = NO;
                [strongSelf.contentView addSubview:errorLabel];
                [NSLayoutConstraint activateConstraints:@[
                    errorLabel.centerXAnchor.constraintEqualToAnchor:strongSelf.contentView.centerXAnchor,
                    errorLabel.centerYAnchor.constraintEqualToAnchor:strongSelf.contentView.centerYAnchor,
                    errorLabel.topAnchor.constraintEqualToAnchor:strongSelf.contentView.topAnchor constant:20,
                    errorLabel.bottomAnchor.constraintEqualToAnchor:strongSelf.contentView.bottomAnchor constant:-20
                ]];
                if (strongSelf.onCellHeightNeedUpdate) {
                    strongSelf.onCellHeightNeedUpdate();
                }
            }
        }];
    }
    return self;
}

// 点击分区头展开收起后,调用table2的reloadData触发contentSize更新即可
- (void)headerTapped:(UITapGestureRecognizer *)gesture {
    NSInteger section = gesture.view.tag;
    self.openSection = self.openSection == section ? -1 : section;
    [self.table2 reloadData];
}
    1. 在Table1的数据源中处理高度更新回调
      在table1的cellForRowAtIndexPath方法中绑定cell的回调,触发table1的高度刷新:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row == 0) { // 第一个内嵌table2的cell
        SPDCustomCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SPDCustomCell" forIndexPath:indexPath];
        __weak typeof(tableView) weakTable = tableView;
        cell.onCellHeightNeedUpdate = ^{
            __strong typeof(weakTable) strongTable = weakTable;
            // 执行begin/endUpdates自动计算高度,不需要reload行
            [strongTable beginUpdates];
            [strongTable endUpdates];
        };
        return cell;
    }
    // 其他cell的逻辑
}
    1. 确保Table1的自动高度配置正确
      确认table1已经开启自动高度:
self.table1.rowHeight = UITableViewAutomaticDimension;
self.table1.estimatedRowHeight = 100; // 设为接近的预估高度即可

内容的提问来源于stack exchange,提问作者Arainty

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 06:54:03