解决模态展示WebView中相对路径链接无法跳转的问题
嘿,这个问题我之前做项目的时候也碰到过!UIWebView处理相对路径链接确实容易踩坑,别用那种读取HTML内容再手动加baseURL的麻烦方法了,试试下面这几个更简洁靠谱的方案:
方案1:利用UIWebViewDelegate拦截链接点击并处理相对路径
这是最直接的解决方式,通过代理方法拦截用户的链接点击行为,手动拼接相对路径和当前页面的baseURL,再决定是在当前WebView加载还是跳转到Safari。
实现步骤很简单,在你的UIViewController里实现webView(_:shouldStartLoadWith:navigationType:)方法:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebView.NavigationType) -> Bool { // 只处理用户主动点击链接的情况,其他导航类型(比如页面自动跳转、刷新)正常放行 guard navigationType == .linkClicked else { return true } guard let currentPageURL = webView.request?.url, let clickedURL = request.url else { return false } // 判断点击的是否是相对路径(没有scheme的就是相对路径,比如"/about.html") if clickedURL.scheme == nil { // 拼接当前页面的baseURL和相对路径,生成完整URL let fullURL = URL(string: clickedURL.absoluteString, relativeTo: currentPageURL)! // 选择1:在当前UIWebView中加载这个完整URL webView.load(URLRequest(url: fullURL)) return false // 阻止默认行为,因为我们已经手动处理了加载 // 选择2:跳转到Safari打开 // UIApplication.shared.open(fullURL) // return false } else { // 如果是绝对路径,你可以选择直接在WebView加载,或者跳Safari UIApplication.shared.open(clickedURL) return false } }
方案2:确保初始加载时设置正确的baseURL
如果你的网页是通过loadHTMLString(_:baseURL:)加载的(比如本地HTML文件或者从服务器获取的HTML字符串),一定要把baseURL参数设置正确——这个参数会告诉WebView如何解析页面里的相对路径。
举个例子,加载本地HTML文件时:
guard let htmlPath = Bundle.main.path(forResource: "index", ofType: "html") else { return } let htmlString = try! String(contentsOfFile: htmlPath) // baseURL设置为HTML文件所在的目录,这样页面里的相对路径会自动基于这个地址解析 let baseURL = URL(fileURLWithPath: Bundle.main.bundlePath) webView.loadHTMLString(htmlString, baseURL: baseURL)
如果是加载服务器返回的HTML字符串,baseURL就设为服务器的根地址(比如https://your-domain.com/),这样WebView会自动把相对路径拼接成完整的服务器URL。
额外建议:迁移到WKWebView(更推荐)
UIWebView其实已经被苹果废弃了,性能和安全性都不如WKWebView。如果你的项目还在使用UIWebView,建议尽快迁移过去。处理相对路径的逻辑类似,只是用WKNavigationDelegate的方法:
func webView(_ webView: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping (WKNavigationActionPolicy) -> Void) { guard navigationAction.navigationType == .linkActivated else { decisionHandler(.allow) return } guard let clickedURL = navigationAction.request.url else { decisionHandler(.cancel) return } if clickedURL.scheme == nil { if let baseURL = webView.url { let fullURL = URL(string: clickedURL.absoluteString, relativeTo: baseURL)! webView.load(URLRequest(url: fullURL)) decisionHandler(.cancel) } else { decisionHandler(.cancel) } } else { UIApplication.shared.open(clickedURL) decisionHandler(.cancel) } }
内容的提问来源于stack exchange,提问作者domdomcodecode
相关产品推荐
相关产品推荐

