
本文详解如何在 swift 中通过 wkwebview 安全、完整地加载内联 html 字符串,并正确引入本地 css/js 资源及动态数据,避免渲染异常、资源 404 或样式失效等问题。
本文详解如何在 swift 中通过 wkwebview 安全、完整地加载内联 html 字符串,并正确引入本地 css/js 资源及动态数据,避免渲染异常、资源 404 或样式失效等问题。
在 iOS 开发中,使用 WKWebView 展示富文本或定制化 HTML 页面是常见需求。但直接拼接 HTML 字符串并调用 loadHTMLString(_:baseURL:) 却常导致页面空白、样式丢失、图片不显示或脚本未执行——根本原因在于:资源路径未正确解析、baseURL 设置缺失、HTML 结构不完整或安全策略拦截。
✅ 正确加载 HTML 的核心步骤
- 确保 HTML 文档结构完整(含 <!DOCTYPE html>、闭合 <html>/<head>/<body>);
- 使用 loadHTMLString(_:baseURL:) 并传入有效的 baseURL,否则 bootstrap.css、app_logo2.png 等相对路径将全部失败;
- 将 CSS/JS/图片等静态资源放入 Bundle,并确保 Build Phase → “Copy Bundle Resources” 中已包含;
- 动态内容需严格转义(如 (strCName) 中的双引号、换行符可能破坏 HTML 结构)。
✅ 完整可运行示例(Swift 5.9+)
import WebKit
class ViewController: UIViewController {
var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
// 1. 初始化 WKWebView
webView = WKWebView(frame: view.bounds)
view.addSubview(webView)
// 2. 构建 HTML(注意:使用多行字符串字面量 + 严格转义)
let escapedName = strCName.replacingOccurrences(of: """, with: "\"")
let escapedAddress = strCAddress.replacingOccurrences(of: """, with: "\"")
let htmlString = """
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Termite Report</title>
<!-- 本地 CSS:路径相对于 baseURL -->
<link rel="stylesheet" href="bootstrap.css">
<link rel="stylesheet" href="styles.css">
<!-- Google Fonts -->
<link href="https://fonts.googleapis.com/css?family=Roboto+Condensed:300,300i,400,400i,700,700i" rel="stylesheet">
<!-- jQuery & Bootstrap JS -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="js/bootstrap.js"></script>
</head>
<body>
<div class="container pdf-wrapper">
<div class="page-breck">
<div class="row">
<div class="col-xs-4">
<div class="pdf-top-middle">
<img src="app_logo2.png" width="400" alt="Company Logo">
</div>
</div>
</div>
<div class="row">
<div class="col-md-3 col-xs-5">
<p class="contactLft">
<b>Name</b> (escapedName)<br>
<b>Phone</b> (phoneNo)<br>
<b>Street Address</b> (escapedAddress)
</p>
</div>
<div class="col-md-6 col-xs-7 text-center">
<p class="contactMidText">
<b>Subterranean Termite Control/Treatment<br>Retreat and Repair Coverage</b><br>
<b>Email</b> (strEmail)
</p>
</div>
</div>
</div>
</div>
</body>
</html>
"""
// 3. 关键:指定 baseURL 为 Bundle 主目录,使相对路径可解析
guard let bundleURL = Bundle.main.resourceURL else {
print("⚠️ Failed to get bundle URL")
return
}
// 4. 加载 HTML(自动解析 bootstrap.css、app_logo2.png 等本地资源)
webView.loadHTMLString(htmlString, baseURL: bundleURL)
}
}⚠️ 必须注意的关键事项
- baseURL 不可为 nil:若传 nil,所有 href/src 相对路径均视为网络请求,导致 404;
- 资源必须在 Bundle 中且路径匹配:例如 bootstrap.css 需位于项目根目录(非子文件夹),否则应调整 baseURL 或路径(如 "css/bootstrap.css");
- 图片宽高单位建议用 px 而非 rem:rem 依赖根字体大小,在无 CSS 重置时行为不可控;
- 动态内容务必转义:strCName 若含 ", <, & 等字符,会破坏 HTML 结构,推荐使用 HTML String Escaping 工具 或手动 .replacingOccurrences(of:with:);
- 调试技巧:在 WKNavigationDelegate 中实现 webView(_:didFail:withError:) 捕获加载错误;启用 Web Inspector(Safari → Develop → [Your Device] → [Page])实时查看控制台报错与网络请求。
✅ 总结
WKWebView.loadHTMLString(_:baseURL:) 是加载内联 HTML 的标准方案,但其可靠性完全取决于 baseURL 的准确性和资源路径的规范性。始终将静态资源纳入 Bundle,用 Bundle.main.resourceURL 作为 baseURL,并对用户输入做 HTML 安全转义——三者结合,即可稳定渲染复杂 HTML 页面,无需依赖远程服务或繁琐的本地服务器方案。











