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

Objective-C迁移UIWebView到WKWebView,如何实现高度自适应内容?

WKWebView 高度自适应内容解决方案(Objective-C)

核心问题原因

WKWebView 无法像 UIWebView 那样通过 sizeThatFits: 获取内容高度,必须通过 JavaScript 注入的方式获取页面实际内容高度,再更新约束常量。

具体实现步骤

1. 配置 WKWebView 并设置代理

在 TMAnswerView.m 的初始化方法中,给 WKWebView 设置 navigationDelegate,同时禁用内部滚动(如果不需要内容滚动):

- (instancetype)initWithFrame:(CGRect)frame {
    self = [super initWithFrame:frame];
    if (self) {
        WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
        self.webView = [[WKWebView alloc] initWithFrame:CGRectZero configuration:config];
        self.webView.navigationDelegate = self;
        self.webView.scrollView.scrollEnabled = NO; // 禁用滚动,确保高度自适应生效
        self.webView.scrollView.bounces = NO;
        
        // 添加布局约束(假设已绑定 heightOfWebView 高度约束)
        [self.webView setTranslatesAutoresizingMaskIntoConstraints:NO];
        [self addSubview:self.webView];
        // 补充你的其他约束(如 leading、trailing、top)
        self.heightOfWebView = [NSLayoutConstraint constraintWithItem:self.webView attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeNotAnAttribute multiplier:1.0 constant:0];
        [self addConstraint:self.heightOfWebView];
    }
    return self;
}

2. 页面加载完成后获取内容高度

实现 WKNavigationDelegate 的页面加载完成回调,通过 JS 获取内容高度并更新约束:

#pragma mark - WKNavigationDelegate
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    // 执行 JS 获取页面实际高度,优先取 document.documentElement.scrollHeight 适配更多场景
    [webView evaluateJavaScript:@"Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)" completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        if (!error && result) {
            CGFloat contentHeight = [result doubleValue];
            // 更新高度约束常量
            self.heightOfWebView.constant = contentHeight;
            // 强制刷新布局
            [self layoutIfNeeded];
        }
    }];
}

3. 处理图片/动态内容加载后的高度变化

如果页面包含图片或动态加载内容,仅靠页面加载完成回调可能获取到的高度不准确,可通过注入 JS 监听页面加载完成(包括图片):

// 在初始化 WKWebViewConfiguration 时添加 UserScript
WKUserScript *heightScript = [[WKUserScript alloc] initWithSource:@"window.addEventListener('load', function() { window.webkit.messageHandlers.webViewHeightCallback.postMessage(Math.max(document.body.scrollHeight, document.documentElement.scrollHeight)); });" injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];
[config.userContentController addUserScript:heightScript];
// 添加消息处理器
[config.userContentController addScriptMessageHandler:self name:@"webViewHeightCallback"];

然后实现 WKScriptMessageHandler 协议方法:

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"webViewHeightCallback"]) {
        CGFloat contentHeight = [message.body doubleValue];
        self.heightOfWebView.constant = contentHeight;
        [self layoutIfNeeded];
    }
}

// 记得在销毁时移除消息处理器,避免循环引用
- (void)dealloc {
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"webViewHeightCallback"];
}

注意事项

  • 确保 WKWebView 的 scrollEnabled 设为 NO,否则内容会滚动,高度自适应效果失效。
  • 如果 WKWebView 设置了内边距(contentInset),需要在计算高度时把内边距值加入约束常量。
  • 若页面存在动态内容(如 AJAX 加载),可进一步注入 JS 使用 MutationObserver 监听 DOM 变化,实时更新高度。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 01:50:30