NTLBridge-Swift 是一个强大且轻量级的 JavaScript 桥接库,专为 iOS 和 macOS 应用程序设计。它能够在您的 Swift/Objective-C 代码和 WKWebView 中运行的 JavaScript 之间实现无缝的双向通信,并完全兼容 https://github.com/netless-io/Whiteboard-bridge 规范。
- 🔄 双向通信:从 JavaScript 调用原生方法,反之亦然
- ⚡ 异步与同步支持:同时支持同步和异步方法调用
- 🛡️ 错误处理:支持JavaScript错误结构化捕获
- 📦 Codable支持:JSONValue支持Codable协议
- ✨ 字面量支持:支持Swift字面量语法
- 🔧 实例方法绑定:支持与实例绑定的方法注册
.package(url: "https://github.com/your-org/NTLBridge-Swift.git", from: "1.0.0")
import NTLBridge
import WebKit
class ViewController: UIViewController {
var webView: NTLWebView!
override func viewDidLoad() {
super.viewDidLoad()
// 创建 web 视图
let config = WKWebViewConfiguration()
webView = NTLWebView(frame: view.bounds, configuration: config)
view.addSubview(webView)
// 启用调试模式(可选)
webView.isDebugMode = true
// 加载 HTML
if let url = Bundle.main.url(forResource: "index", withExtension:
"html") {
webView.loadFileURL(url, allowingReadAccessTo:
url.deletingLastPathComponent())
}
}
}
// 注册简单方法
webView.register(methodName: "getDeviceInfo") { param in
return [
"device": UIDevice.current.model,
"system": UIDevice.current.systemVersion
]
}
// 注册与实例绑定的方法
class DataService {
func fetchUserData(_ userId: String) -> [String: Any] {
return ["id": userId, "name": "User \(userId)"]
}
}
let dataService = DataService()
webView.register(methodName: "getUserData", target: dataService) { target, param in
guard let userId = param.stringValue else { return nil }
return target.fetchUserData(userId)
}
// 注册异步方法
webView.registerAsync(methodName: "fetchData") { param, completion in
// 模拟网络调用
DispatchQueue.global().async {
let result = "数据获取成功"
completion(.success(.string(result)))
}
}
// 使用字面量语法
webView.register(methodName: "calculate") { param in
return ["result": 42, "success": true]
}
// 调用 JavaScript 方法
webView.callHandler("showAlert", arguments: ["来自 Swift 的问候!"]) { result in
switch result {
case .success(let value):
print("JS 响应: \(value ?? .null)")
case .failure(let error):
print("错误: \(error)")
}
}
// 使用字面量语法调用
webView.callHandler("calculate", arguments: [10, 20, "add"])
// 支持Codable类型
struct User: Codable {
let id: String
let name: String
}
let user = User(id: "123", name: "张三")
webView.callHandler("updateUser", arguments: [user])
Web 端使用 https://github.com/netless-io/Whiteboard-bridge 实现无缝集成:版本需要大于 @netless/[email protected]
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>桥接测试</title>
<script type="module">
import { bridge } from
"https://github.com/netless-io/Whiteboard-bridge";
// 使桥接器全局可用
window.bridge = bridge;
// 调用原生方法
const deviceInfo = bridge.syncCall("getDeviceInfo");
console.log("设备信息:", deviceInfo);
// 异步调用
bridge.asyncCall("fetchData", { userId: 123 })
.then(result => console.log(result))
.catch(error => console.error(error));
</script>
</head>
<body>
<h1>桥接测试页面</h1>
</body>
</html>
// 支持所有Swift字面量语法
let stringValue: JSONValue = "Hello"
let numberValue: JSONValue = 42
let boolValue: JSONValue = true
let arrayValue: JSONValue = [1, 2, 3]
let dictValue: JSONValue = ["key": "value"]
let nullValue: JSONValue = nil
// 在桥接调用中使用
webView.register(methodName: "getConfig") { _ in
return [
"appName": "MyApp",
"version": 1.0,
"features": ["feature1", "feature2"],
"debug": false
]
}
// 定义Codable类型
struct Config: Codable {
let apiUrl: String
let timeout: Int
let enableCache: Bool
}
// 在桥接中使用
webView.register(methodName: "loadConfig") { _ in
let config = Config(apiUrl: "https://api.example.com", timeout: 30, enableCache: true)
return try? JSONValue(codable: config)
}
// JavaScript端错误会被自动捕获并传递到Swift端
// JavaScript代码示例:
bridge.call("someMethod", { error, result }) {
if (error) {
console.error("Error:", error);
return;
}
console.log("Result:", result);
}
// Swift端会收到结构化的错误信息,包括:
// - 错误名称
// - 错误消息
// - 堆栈跟踪
// 启用调试模式以查看详细的桥接日志
webView.isDebugMode = true
MIT License - 详见 LICENSE 文件