ios - 异步调整 UITableViewCell 与生成的 UIView-Encapsulated-Layout-Height

标签 ios uitableview ios8 autolayout constraints

我正在尝试使用 iOS 8“从内部”调整表格 View 单元格的大小,因此实现

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

但使用:

self.tableView.rowHeight = UITableViewAutomaticDimension;
self.tableView.estimatedRowHeight = 200;

单元格从上到下都有约束。

该单元格包含(除其他事项外)一个 UIWebview,它在加载后通过向 ScrollView 询问其高度来异步知道其大小:

CGFloat fittingHeight = self.messageTextWebView.scrollView.contentSize.height;

(这是一个变体,其中 webview 包含在另一个 View 中,并且该 View 会相应地调整大小)。

因为发生这种情况时整个自动布局过程已经完成,所以我设置了

[self setNeedsUpdateConstraints];

在单元格中的 View 上,它通过 layoutSubviews 冒泡到单元格并再次下降。

最后,我得到了可怕的 Unable to simultaneously satisfy constraints.。打破一切的约束是

"<NSLayoutConstraint:0x7f8c29d157f0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f8c2b063eb0(270)]>"

此约束是在第一次计算单元格时由 TableView 创建的。

它杀死了我自己:

Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x7fa8a8515b70 V:[UIView:0x7fa8aa0263e0(263)]>

虽然我将约束的优先级设置为 1000 并将压缩阻力设置为 1000,但我无法覆盖 TableView 创建的约束。

令人沮丧的是: 如果我用一个简单的多行标签替换 web View 并且知道第一个单元格布局期间的所有大小,那么一切都会完美无缺。 Web View 加载系统的异步特性迫使我在第一次呈现单元格后更改布局。

现在我的问题:

有什么办法解决这个问题吗?我真的不想重新加载单元格。如果该单元格是屏幕上唯一的单元格,则它不会被重复使用,整个过程将重新开始。 这甚至可能吗?或者 UITableView 架构是否依赖于外部约束来正确呈现自身?

为了好玩,我设置了

self.translatesAutoresizingMaskIntoConstraints = NO;

在单元格本身上,导致单元格的大小为 0,0 且约束为:

"<NSLayoutConstraint:0x7f88506663a0 'UIView-Encapsulated-Layout-Height' V:[UITableViewCellContentView:0x7f8850648400(0)]>"

但它仍然存在......

感谢您的帮助。

顺便说一句:我已经阅读了有关此事的所有内容,包括: Using Auto Layout in UITableView for dynamic cell layouts & variable row heights

最佳答案

这是一个 UITableViewCell 子类,它管理 UIWebView 并为 UITableView 设置正确调整其高度以使用 UITableViewAutomaticDimension.

主要是为UIWebView高度维护一个NSLayoutConstraint。在 updateConstraints 中更新其常量。告诉父 TableView 在发生变化时重新计算单元格高度。

@implementation WebTableViewCell
{
    IBOutlet UIWebView*             _webview; // glued to cell content view using edge constraints

    IBOutlet NSLayoutConstraint*    _heightConstraint; // height constraint for the webview itself
}

- (void) awakeFromNib
{
    _webview.scrollView.scrollEnabled = NO;

    // use this to test various document heights
    //  [_webview loadHTMLString: @"<html><body style='height:100px;'>Hello, World</body></html>" baseURL: nil];

    // or, a real web page
    [_webview loadRequest: [NSURLRequest requestWithURL: [NSURL URLWithString: @"http://stackoverflow.com/users/291788/tomswift"]]];
}

- (void) updateConstraints
{
    [super updateConstraints];

    // get the document height.
    CGFloat height = [[_webview stringByEvaluatingJavaScriptFromString: @"document.height"] floatValue];
    if ( _heightConstraint.constant != height )
    {
        // update
        _heightConstraint.constant = height;

        // ask the tableview to recalc heights
        dispatch_async(dispatch_get_main_queue(), ^{

            UITableView* tableView = (UITableView*)self.superview;
            while ( tableView != nil && ![tableView isKindOfClass: [UITableView class]] )
                tableView = (UITableView*)tableView.superview;


            [tableView beginUpdates];
            [tableView endUpdates];
        });
    }
}

- (void) webViewDidFinishLoad:(UIWebView *)webView
{
    [self setNeedsUpdateConstraints];
}

@end

关于ios - 异步调整 UITableViewCell 与生成的 UIView-Encapsulated-Layout-Height,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26957895/

相关文章:

json - 为用户提供从 Firebase 下载所有内容的选项

ios - 即使值的数量与行数匹配,索引也会超出范围错误

iOS 8 - 以横向模式启动应用程序

ios - 条件绑定(bind) : if let error – Initializer for conditional binding must have Optional type

ios - 重新加载表格后,UILabel的背景颜色变得清晰

ios - 应用商店拒绝,因为 "should have all included URLs fully functional"

ios - Spinner(UIActivityIndi​​cator) 在 iOS 中不显示

ios - iOS 8.0 公开版本的内部版本号是多少?

iOS 通用应用程序似乎在手机上略微放大

ios - 通过 FBSDKShareLinkContent 在 Messenger 上分享内容失败