NTLBridge-Swift 是一个强大且轻量级的 JavaScript 桥接库,专为 iOS 和 macOS 应用程序设计。它能够在您的 Swift/Objective-C 代码和 WKWebView 中运行的 JavaScript 之间实现无缝的双向通信,并完全兼容 https://github.com/netless-io/Whiteboard-bridge 规范。
- 双向通信
- 支持异步与同步
- 支持JavaScript错误结构化捕获
- Codable支持
- 字面量支持
.package(url: "https://github.com/netless-io/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
]
}
// 注册类型安全的方法
webView.register(methodName: "getUserData", expecting: String.self) { userId in
return [
"id": userId,
"name": "User \(userId)"
]
}
// 注册自定义类型的方法
struct UserData: Codable {
let id: String
let name: String
}
webView.register(methodName: "createUser", expecting: UserData.self) { userData in
return "User created: \(userData.name)"
}
// 注册异步方法
webView.registerAsync(methodName: "fetchData") { param, completion in
// 模拟网络调用
DispatchQueue.global().async {
let result = "数据获取成功"
completion(.success(.string(result)))
}
}
// 注册类型安全的异步方法
struct RequestData: Codable {
let userId: String
let type: String
}
webView.registerAsync(methodName: "fetchUserData", expecting: RequestData.self) { requestData, completion in
DispatchQueue.global().async {
// 模拟异步网络请求
let userData = ["id": requestData.userId, "name": "User \(requestData.userId)"]
completion(.success(.dictionary(userData.mapValues { .string($0) })))
}
}
// 使用字面量语法
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 响应: \(String(describing: value))")
case .failure(let error):
print("错误: \(error)")
}
}
// 使用类型安全的调用方法
struct User: Codable {
let id: String
let name: String
}
webView.callTypedHandler("updateUser", arguments: [user], expecting: User.self) { result in
switch result {
case .success(let updatedUser):
print("更新后的用户: \(updatedUser.name)")
case .failure(let error):
print("错误: \(error)")
}
}
// 支持Codable类型
let user = User(id: "123", name: "张三")
webView.callHandler("updateUser", arguments: [user])
// 使用 JSON 字面量调用
webView.callHandler("calculate", arguments: [10, 20, "add"])Web 端使用 @netless/webview-bridge 实现无缝集成(版本需要 >= 0.2.1):
// 支持所有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
]
}// 取消注册方法
webView.unregister(methodName: "getDeviceInfo")
// 获取已注册的方法列表
let methods = webView.registeredMethods
print("已注册的方法: \(methods)")
// 类型安全的异步注册
struct LoginRequest: Codable {
let username: String
let password: String
}
struct LoginResponse: Codable {
let token: String
let userId: String
}
webView.registerAsync(methodName: "login", expecting: LoginRequest.self) { request, completion in
// 处理登录逻辑
let response = LoginResponse(token: "abc123", userId: request.username)
completion(.success(.string(response.token)))
}
// 使用 JSON 字符串调用
webView.callHandler("updateConfig", jsonString: "{\"theme\":\"dark\",\"fontSize\":16}")// 定义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)
}MIT License - 详见 LICENSE 文件