JSBridge

连接你的 JavaScript 库以便在 Swift 中使用 🚀

安装

SwiftPM

dependencies: [
    .package(url: "https://github.com/LinusU/JSBridge", from: "1.0.0"),
]

Carthage

github "LinusU/JSBridge" ~> 1.0.0

用法

foobar.js

window.Foobar = {
  add (a, b) {
    return a + b
  },
  greet (name) {
    return `Hello, ${name}!`
  },
  async fetch (url) {
    const response = await fetch(url)
    const body = await response.text()

    return { status: response.status, body }
  }
}

Foobar.swift

struct FetchResponse: Decodable {
    let status: Int
    let body: String
}

class Foobar {
    static internal let bridge: JSBridge = {
        let libraryPath = Bundle.main.path(forResource: "foobar", ofType: "js")!
        let libraryCode = try! String(contentsOfFile: libraryPath)

        return JSBridge(libraryCode: libraryCode)
    }()

    static func add(_ lhs: Int, _ rhs: Int) -> Promise<Int> {
        return Foobar.bridge.call(function: "Foobar.add", withArgs: (lhs, rhs)) as Promise<Int>
    }

    static func greet(name: String) -> Promise<String> {
        return Foobar.bridge.call(function: "Foobar.greet", withArg: name) as Promise<String>
    }

    static func fetch(url: URL) -> Promise<FetchResponse> {
        return Foobar.bridge.call(function: "Foobar.fetch", withArg: url) as Promise<FetchResponse>
    }
}

API

JSBridge(libraryCode: String)

创建一个新的 JSBridge 实例,使用提供的库源代码。

libraryCode 应该是一个 JavaScript 字符串,它将一个或多个函数附加到 window 对象。 然后可以使用 call 方法调用这些函数。

call(function: String) -> Promise<Void>

调用一个没有参数的函数,忽略返回值。返回的 Promise 将在函数完成运行后解决。

call<Result: Decodable>(function: String) -> Promise<Result>

调用一个没有参数的函数。返回的 Promise 将使用函数的返回值解决。

call<A: Encodable>(function: String, withArg: A) -> Promise<Void>

调用一个带单个参数的函数,忽略返回值。返回的 Promise 将在函数完成运行后解决。

call<Result: Decodable, A: Encodable>(function: String, withArg: A) -> Promise<Result>

调用一个带单个参数的函数。返回的 Promise 将使用函数的返回值解决。

call<A: Encodable, B: Encodable, ...>(function: String, withArgs: (A, B, ...)) -> Promise<Void>

调用一个带有多个参数的函数,忽略返回值。返回的 Promise 将在函数完成运行后解决。

call<Result: Decodable, A: Encodable, B: Encodable, ...>(function: String, withArgs: (A, B, ...)) -> Promise<Result>

调用一个带有多个参数的函数。返回的 Promise 将使用函数的返回值解决。

iOS

为了能够在 iOS 上使用 JSBridge,你需要给 JSBridge 提供一个连接到你的视图层次结构的钩子。 否则,WKWebView 将被操作系统挂起,并且你的 Promises 将永远不会解决。

这可以通过在使用任何 JSBridge 实例之前使用 setGlobalUIHook 函数来实现。

App

// Can be called from anywhere, e.g. your AppDelegate
JSBridge.setGlobalUIHook(window: UIApplication.shared.windows.first)

App Extension (应用程序扩展)

// From within your root view controller
JSBridge.setGlobalUIHook(viewController: self)

Hacking (开发)

Xcode 项目是使用 XcodeGenproject.yml 自动生成的。 它仅因为 Carthage 需要它才被检入,请勿手动编辑它。

$ mint run yonaskolb/xcodegen
💾  Saved project to JSBridge.xcodeproj