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

