FlexHybridApp 1.0.4

FlexHybridApp 1.0.4

kyun-J 维护。



  • 作者
  • Kyun-J

韩语 README

Android 版本

支持 TypeScript

FlexibleHybrid

FlexHybrid 简化了 WKWebView 和 Native 之间的接口,包括异步处理。
它还提供了几个方便的功能来使用 WKWebView。

如何添加框架

在 Podfile 中添加

  pod 'FlexHybridApp'

iOS 部署目标为 10.0

关键特性

  1. 它与 Android 版本 具有相似的编程规则和功能。
  2. WKWebView 和 Native 之间的接口以异步方式工作。
    1. 在 Web 上调用和返回 Promise
    2. Native 在一个单独的 并发队列 上进行操作。
  3. 使用 Swift Closure 定义接口操作。
  4. 可以将数据传输到 模型对象
  5. 通过指定能够进行接口操作的 URL,可以防止 非期望网站 从 Native 进行调用。

还包括其他特性...

FlexComponent

为了利用 FlexWebView 的功能,您必须使用 FlexComponent。
FlexComponent是用FlexWebView创建的,你还可以在声明FlexWebView时对其进行设置。
FlexComponent还包括WebView的WKWebViewConfiguration作为参数。

界面基本使用

基本上,界面可以按照以下模式进行注册和使用。
所有界面操作都是异步的。
在Web上,它将变成挂起状态,直到发生响应。

Web到本地

界面注册

界面必须在页面加载到FlexWebView之前设置。

// in swift
var component = FlexComponent()
component.setInterface("funcName") { args in
    return "received from web - \(args[0]?.toString() ?? "no value"), return to web - \(100)"
}
var flexWebView = FlexWebView(frame: self.view.frame, component: component)
flexWebView.load(someUrl)

使用界面

// in js
const test = async (req) => {
  const res = await $flex.funcName(req);
  console.log(res); // received from web - 200, return to web - 100
};
test(200);

本地到Web

界面注册

$flex对象加载后(可以在$flex Load时间上检查window.onFlexLoad函数),则注册界面。

// in js
window.onFlexLoad = () => {
  $flex.web.funcName = async (req) => {
    return await new Promise((resolve) => {
      setTimeout(() => resolve(`received from web - ${req}`), 100);
    });
  };
};

使用接口。

// in swift
component.evalFlexFunc("funcName", "sendData") { response in
    print(response.toString()!) // received from web - sendData
}

高级接口使用

FlexData

从Web接收的数据被转换为FlexData对象以实现类型安全使用。
在Web到原生的接口中,来自Web的函数传递的参数将被转发到Array

// in js
$flex.funcName("test1", 2, 3.1, true, [0, 1, 2], { test: "object" }, "reified");
component.setInterface("funcName") { args in
    if (args == nil) return

    var first = args[0].asString() // "test"
    var second = args[1].asInt() // 2
    var third = args[2].asDouble() // 3.1
    var fourth = args[3].asBool() // true
    var fifth = args[4].asArray() // array of FlexData(0), FlexData(1), FlexData(2)
    var sixth = args[5].asDictionary() // map of first key - test, value - FlexData("object")
    var seventh: String? = args[6].reified() // "reified"
}

模型对象

用于接口的数据可以作为模型对象使用。
此时,以下规则适用。

  1. 模型对象必须 继承Codable
  2. 在Web中,它被转换为一个对象形式。
  3. 当从原生接收模型对象作为参数时,您必须传递与Web中相应模型对应的唯一一个对象。
// in swift
struct TestModel: Codable {
  var name: String
  var data2: TestModel2
}

struct TestModel2: Codable {
  var testInt: Int
}

struct ArgsTestModel: Codable {
  var testModel: TestModel
}

component.setInterface("modelTest") { args in
    return TestModel("test", TestModel2(2000))
}

component.setInterface("modelArgsTest") { (req: ArgsTestModel?) -> Void in
    print(req?.testModel.data2.testInt) // 2000
}
// in js
const test = async () => {
  const model = await $flex.modelTest(); // model is { name: 'test', data2: { testInt: 2000 } }
  await $flex.modelArgsTest({ testModel: model });
};
test();

动作接口

在Web到原生的接口中,除了指定的闭包代码块之外,这是一种返回值的方式。
动作对象允许你在代码的期望位置返回值。
此时,Web处于 挂起 状态,直到发生响应。
此外,已响应一次的动作对象不能再次使用。

var mAction: FlexAction? = null

struct LocationResult: Codable {
  var latitude: Double?
  var longtitude: Double?
}

component.setAction("actionTest") { (action, _) in
    self.mAction = action
    self.getLocation()
}

func getLocation() {
  let status = CLLocationManager.authorizationStatus()
  var locationResult = LocationResult();
  switch status {
  case .authorizedAlways, .authorizedWhenInUse :
      self.locationManager.desiredAccuracy = kCLLocationAccuracyBest
      self.locationManager.startUpdatingLocation()
      let coor = self.locationManager.location?.coordinate
      mAction?.promiseReturn(
        LocationResult(latitude: Double(coor?.latitude ?? 0), longtitude: Double(coor?.longitude ?? 0))
      )
      break
  default:
    mAction?.promiseReturn()
    break
  }
}

推荐声明闭包

这是一种便于声明和组织定义接口行为的闭包特征。
您可以通过FlexClosure类中预定义的函数创建闭包。

var closureVar = FlexClosure.interface { args in
    ... some job
}
var closureActionVar = FlexClosure.action { (action, args) in
    ... come job
}

component.setInterface("closureVarTest", closureVar)
component.setAction("closureActionVarTest", closureActionVar)

Web至本地接口超时设置

由于接口操作是异步的,Web端可能会陷入无限等待状态。
因此,可以设置接口的超时,当发生超时时,会切换到拒绝状态。
如果未设置超时,默认值为60000毫秒。

设置默认超时

您可以为超时指定默认值。如果未为每个接口设置超时,则默认设置相应的值。
将值设为零不会导致超时并无限期等待。
单位是毫秒。

var timeout = 1000
component.setInterfaceTimeout(timeout)

为每个接口指定超时

在设置接口时,您可以指定该接口的超时时间。
将值设为零不会导致超时并无限期等待。
单位是毫秒。

var timeout = 200
component.setInterface("funcName", timeout) { args in }

接口事件监听器

初始化接口模块时,会监听接口的成功、失败及超时的相关事件。

// Listen for specific events
component.addEventListener(FlexEvent.EXCEPTION) { (type, url, funcName, msg) in
  print("type: \(type.name) url: \(url) funcName: \(funcName) msg: \(msg)")
}

// Listen to all events
var AllListener = { (type, url, funcName, msg) in
  print("type: \(type.name) url: \(url) funcName: \(funcName) msg: \(msg)")
}
flexWebView.addEventListener(AllListener)

// Remove specific EventListener
flexWebView.removeEventListener(AllListener)

// Remove all EventListeners
flexWebView.removeAllEventListener()

FlexWebView特性

URL限制

这是一个防止加载到非预期网站并设置是否允许特定URL接口的功能。
该功能通过WKContentRule实现,因此在使用时需要小心,因为它可以通过WKWebViewConfiguration中的removeAllContentRuleList函数被删除。

BaseUrl

BaseUrl是在不需要URL限制的情况下设置接口可用性的功能。
如果未设置AllowUrlList和BaseUrl,FlexWebView允许访问所有网站,但接口功能不可用。
如果仅设置BaseUrl,允许访问所有网站,并且接口仅对匹配BaseUrl的URL打开。

component.setBaseUrl("www.myurl.com")

在设置URL时可以使用正则表达式。

component.setBaseUrl(".*.myurl.com")

AllowUrlList

仅适用于iOS 11.0及以上版本。

设置AllowUrlList会阻止访问除已设置URL和BaseUrl以外的所有URL。

component.addAllowUrl(".*.myurl.com")

在设置URL时允许接口,请将true添加到addAllowUrl函数的第二个canFlexLoad属性中。

component.addAllowUrl(".*.myurl.com", canFlexLoad: true)

自动管理Cookie

仅适用于iOS 11.0及以上版本。
这是一个非常基本的功能,因此请直接在出现问题时在实现中直接实现与Cookie相关功能。
这是一个自动维护Cookie的功能。
默认值为不活跃,激活功能时自动运行。
在应用中启用该功能的FlexWebView共享所有Cookie。

component.setAutoCookieManage(true) // activate
component.setAutoCookieManage(true, clearAll: true) // activate and delete all cookies

Web控制台消息输出。

显示Web控制台的.log、debug、error、warn和info消息到xcode的输出窗口中。
默认情况下已启用。

此输出可能与Web上的控制台消息不同。

component.setShowWebViewConsole(true)

FileAccess

一次设置allowAccessFromFileURLs和allowUniversalAccessFromFileURLs的能力。

component.setAllowsUrlAccessInFile(true)

在js中使用

$flex Object

$flex Object是由FlexWebView和Promise之间的接口组成的对象。
在webview加载页面时,$flex会在页面运行时声明在web页面中。
当$flex加载完成后,您可以检查window.onFlexLoad函数。
$flex也可以在任何可访问的框架中使用。(例如)不违反Cross-Origin规则的自定义框架。
$ flex对象的组件如下。

window.onFlexLoad; // $flex is called upon completion of loading.
$flex; // Object that contains functions that can call Native area as WebToNative
$flex.version; // get Library version
$flex.web; // Object used to add and use functions to be used for NativeToWeb
$flex.device; // Current Device Info
$flex.isAndroid; // false
$flex.isiOS; // true
$fles.isScript; // false

ToDo

应用Swift 5.5的async awit。
Flutter版本FlexHybirdApp。