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

WKWebView无法被约束在安全区域内的问题求助

解决WKWebView超出安全区域的问题

嘿,我看到你的问题了,这其实是一个很常见的新手坑——你同时混用了Storyboard可视化布局和代码手动创建视图,导致你在Storyboard里设置的安全区域约束完全没生效!

问题根源分析

你在代码里重写了loadView()方法,并且直接把view赋值成了自己手动创建的WKWebView:

override func loadView() {
    let webConfiguration = WKWebViewConfiguration()
    webView = WKWebView(frame: .zero, configuration: webConfiguration)
    webView.uiDelegate = self
    view = webView // 这里直接替换了视图控制器的根视图
}

当你手动实现loadView()时,iOS系统会跳过从Storyboard加载视图的流程,也就是说你在Storyboard里给webView添加的所有约束、IBOutlet关联都不会被应用。这个手动创建的webView默认是没有安全区域约束的,所以运行时会直接占满整个屏幕,覆盖状态栏区域。

解决方案(二选一即可)

方案1:保留Storyboard布局(推荐新手)

如果你想继续用Storyboard设置约束,只需要删除loadView()方法,让系统自动从Storyboard加载视图即可。修改后的代码如下:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    @IBOutlet var webView: WKWebView! // 这个IBOutlet会从Storyboard正常关联

    override func viewDidLoad() {
        super.viewDidLoad()
        webView.uiDelegate = self // 别忘了设置代理
        
        let url = Bundle.main.url(forResource: "bulk_material_table", withExtension: "html")!
        webView.loadFileURL(url, allowingReadAccessTo: url)
        // 注意:你之前调用了两次load,其实只需要一次就行,这里保留其中一个就可以
        // let request = URLRequest(url: url)
        // webView.load(request)
    }
}

这样修改后,你在Storyboard里给webView设置的安全区域约束就会正常生效,网页内容就不会跑到状态栏后面了。

方案2:纯代码实现(完全脱离Storyboard)

如果你想完全用代码创建视图,那需要删掉Storyboard里的webView,然后在代码里手动给webView添加安全区域约束。修改后的代码如下:

import UIKit
import WebKit

class ViewController: UIViewController, WKUIDelegate {
    var webView: WKWebView! // 这里不需要IBOutlet

    override func loadView() {
        let webConfiguration = WKWebViewConfiguration()
        webView = WKWebView(frame: .zero, configuration: webConfiguration)
        webView.uiDelegate = self
        
        // 把webView添加到视图控制器的根视图,而不是直接替换view
        view = UIView()
        view.addSubview(webView)
        
        // 开启自动布局
        webView.translatesAutoresizingMaskIntoConstraints = false
        
        // 添加安全区域约束
        NSLayoutConstraint.activate([
            webView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
            webView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor),
            webView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor),
            webView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor)
        ])
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let url = Bundle.main.url(forResource: "bulk_material_table", withExtension: "html")!
        webView.loadFileURL(url, allowingReadAccessTo: url)
    }
}

这里的关键是:不再直接把webView设为根视图,而是先创建一个根视图,把webView作为子视图添加进去,然后手动绑定到安全区域的布局指南上。

额外小提示

你之前在viewDidLoad()里连续调用了两次load方法:webView.loadFileURL(...)和webView.load(request),其实只需要其中一次就够了,重复加载会浪费资源,记得删掉其中一个哦~

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 09:28:55