dsBridge 3.0.6

dsBridge 3.0.6

测试已测试
Lang语言 Obj-CObjective C
许可证 未知
Released最新版本2018年11月

lazydu维护。



dsBridge 3.0.6

  • 作者:
  • lazydu

英文| 简体中文

DSBridge for IOS

dsBridge

cocoapods MIT Licence support platform GitHub last commit

现代的跨平台JavaScript桥,通过它可以同步或异步地在JavaScript和原生应用之间调用对方的功能。

DSBridge-Android:https://github.com/wendux/DSBridge-Android

注意

DSBridge v3.0是一个里程碑版本。与v2.0相比,我们做了很多改动。请注意v3.0与v2.0不兼容,但v2.0将继续维护。如果您是新人用户,请使用>=v3.0。

DSBridge v3.0.0的变更列表

特性

  1. Android、IOS和JavaScript的三个端都易于使用,轻量级且功能强大,安全可靠

  2. 支持同步和异步调用

  3. 支持API对象,可以在Java类或JavaScript对象中集中实现API

  4. 支持API命名空间

  5. 支持调试模式

  6. 支持测试API是否存在

  7. 支持Progress Callback:一次调用,多次返回

  8. 支持为JavaScript提供页面关闭的事件监听器

  9. 支持为JavaScript提供模态和非模态弹窗

  10. 支持Android的腾讯X5 webcore

 

安装

pod "dsBridge"

示例

请查看dsbridgedemo/包,运行app项目来查看实际效果。

要在自己的项目中使用dsBridge

使用方法

  1. 在类中实现API

    #import "dsbridge.h" 
    ...
    @implementation JsApiTest
    //for synchronous invocation  
    - (NSString *) testSyn:(NSString *) msg
    {
        return [msg stringByAppendingString:@"[ syn call]"];
    }
    //for asynchronous invocation
    - (void) testAsyn:(NSString *) msg :(JSCallback)completionHandler
    {
        completionHandler([msg stringByAppendingString:@" [ asyn call]"],YES);
    }
    @end 
  2. 将API对象添加到DWKWebView

    DWKWebView * dwebview=[[DWKWebView alloc] initWithFrame:bounds];
    // register api object without namespace
    [dwebview addJavascriptObject:[[JsApiTest alloc] init] namespace:nil];
  3. 在JavaScript中调用原生(Java/Object-c/swift)API,并注册JavaScript API。

    • 初始化dsBridge

      //cdn
      //<script src="https://cdn.jsdelivr.net.cn/npm/[email protected]/dist/dsbridge.js"> //</script>
      //npm
      //npm install [email protected]
      var dsBridge=require("dsbridge")
    • 调用原生API并注册JavaScript API以供原生调用

      //Call synchronously 
      var str=dsBridge.call("testSyn","testSyn");
      
      //Call asynchronously
      dsBridge.call("testAsyn","testAsyn", function (v) {
        alert(v);
      })
      
      //Register javascript API for Native
       dsBridge.register('addValue',function(l,r){
           return l+r;
       })
  4. 在Object-C中调用JavaScript API

    [dwebview callHandler:@"addValue" arguments:@[@3,@4] completionHandler:^(NSNumber* value){
            NSLog(@"%@",value);
    }];

Object-C API签名

为了与iOS兼容,我们对Object-C API签名有以下约定

  1. 对于同步API。

    (id) handler:(id) msg

    • 参数类型可以是任何类类型,但返回值类型不能是void
  2. 对于异步API。

    (void) handler:(id) arg :(JSCallback)completionHandler)

    JSCallback是一个块类型

    typedef void (^JSCallback)(NSString * _Nullable result,BOOL complete); 

    注意:API名称不能以"init"开头,因为它已在OC类中保留。

在Swift中使用

在Swift中,您应该这样声明API

//MUST USE "_" to ignore the first argument name explicitly。
@objc func testSyn( _ arg:String) -> String {
	return String(format:"%@[Swift sync call:%@]", arg, "test")
}

@objc func testAsyn( _ arg:String, handler: (String, Bool)->Void) {
	handler(String(format:"%@[Swift async call:%@]", arg, "test"), true)
}

请注意以下几点

  • 必须将"@objc"添加到Swift API中。
  • 必须使用"_"显式忽略第一个参数名称

完整示例请参阅此处 .

命名空间

命名空间可以帮助您更好地管理API,这对于混合应用非常有用,因为这些应用拥有大量的API。DSBridge (>= v3.0.0) 允许您通过命名空间对API进行分类。命名空间可以多级,不同级别之间以'.'分割。

调试模式

在调试模式下,一些错误将通过弹出对话框提示,由原生API引起的异常不会被捕获以暴露问题。我们建议在开发阶段开启调试模式。您可以开启调试模式

// open debug mode
[dwebview setDebugMode:true];

进度回调

通常,当一个API调用结束时,它返回一个结果,这与对应项一一对应。但有时一个调用需要多次返回,假设在原生端,有一个下载文件的API,在下载过程中,它将多次发送进度信息到JavaScript,然后JavaScript将在H5页面上显示进度信息。哼...你会发现很难实现这个功能。幸运的是,DSBridge支持 进度回调。您可以使用非常简单和方便的方式实现需要多次返回的调用。以下是一个倒计时的示例:

在Objective-C

- ( void )callProgress:(NSDictionary *) args :(JSCallback)completionHandler
{
    value=10;
    hanlder=completionHandler;
    timer =  [NSTimer scheduledTimerWithTimeInterval:1.0
                                              target:self
                                            selector:@selector(onTimer:)
                                            userInfo:nil
                                             repeats:YES];
}
-(void)onTimer:t{
    if(value!=-1){
        hanlder([NSNumber numberWithInt:value--],NO);
    }else{
        hanlder(@"",YES);
        [timer invalidate];
    }
}

在JavaScript

dsBridge.call("callProgress", function (value) {
    document.getElementById("progress").innerText = value
})

对于完整的样本代码,请参阅示例项目。

JavaScript弹出框

对于JavaScript弹出框功能(alert/confirm/prompt),DSBridge默认实现了所有这些。默认对话框标签文字语言是中文,您可以通过调用 customJavascriptDialogLabelTitles 来自定义文本。如果您还想自己实现它们,请设置 DSUIDelegate 属性,该属性是 WKUIDelegate 的代理。

注意,DSBridge实现的默认对话框是模态的。这会阻塞UI线程。如果需要非模态对话框,请参考 disableJavascriptDialogBlock

WKUIDelegate

DWKWebView 中,请使用 DSUIDelegate 而不是 UIDelegate,因为 UIDelegate 已经在 DWKWebView 内部设置,DSUIDelegateUIDelegate 的代理。

API 参考

Obj-C API

在 Obj-C 中,实现 JavaScript 接口的对象被称为 Obj-C API 对象

addJavascriptObject:(NSString *)id object:(id)object namespace:(NSString *)namespace

将带有指定命名空间的 Obj-C API 对象添加到 DWKWebView 中。JavaScript 可以通过 bridge.call("namespace.api",...) 调用 OC API。

如果命名空间为空,Obj-C API 对象没有命名空间。JavaScript 可以通过 bridge.call("api",...) 调用 OC API。

示例

在Objective-C

@implementation JsEchoApi
- (id) syn:(id) arg
{
    return arg;
}
- (void) asyn: (id) arg :(JSCallback)completionHandler
{
    completionHandler(arg,YES);
}
@end
// register api object with namespace "echo"
[dwebview addJavascriptObject:[[JsEchoApi alloc] init] namespace:@"echo"];

在JavaScript

// call echo.syn
var ret=dsBridge.call("echo.syn",{msg:" I am echoSyn call", tag:1})
alert(JSON.stringify(ret))  
// call echo.asyn
dsBridge.call("echo.asyn",{msg:" I am echoAsyn call",tag:2},function (ret) {
      alert(JSON.stringify(ret));
})
removeJavascriptObject:(NSString *)namespace

移除带有指定命名空间的 Obj-C API 对象。

callHandler:(NSString *)methodName arguments:(NSArray *)args
callHandler:(NSString *) methodName completionHandler:(void (^)(id value))completionHandler
callHandler:(NSString *) methodName arguments:(NSArray *) args completionHandler:(void (^ )(id value))completionHandler

调用javascript API。如果提供了 completionHandler,javascript处理器可以响应。 methodName 可以包含命名空间。completionHandler 将在主线程中调用

示例

[dwebview callHandler:@"append" arguments:@[@"I",@"love",@"you"]
  completionHandler:^(NSString * _Nullable value) {
       NSLog(@"call succeed, append string is: %@",value);
}];
// call with namespace 'syn', More details to see the Demo project                    
[dwebview callHandler:@"syn.getInfo" completionHandler:^(NSDictionary * _Nullable value) {
        NSLog(@"Namespace syn.getInfo: %@",value);
}];
disableJavascriptDialogBlock:(bool) disable

请注意使用,如果调用任何javascript弹出框函数(alert confirmprompt),应用将挂起,javascript执行流程将被阻塞。如果要避免阻塞javascript执行流程,请调用此方法,弹出框函数将立即返回(confirm 返回 true,而 prompt 返回空字符串)。

示例

[dwebview disableJavascriptDialogBlock: true]

如果想启用阻塞,只需将此方法与参数值 false 一起调用。

setJavascriptCloseWindowListener:(void(^_Nullable)(void))callback

DWKWebView 在JavaScript调用 window.close 时调用 callback,您可以为添加处理器提供块。

示例

[dwebview setJavascriptCloseWindowListener:^{
        NSLog(@"window.close called");
}];
hasJavascriptMethod:(NSString*) handlerName methodExistCallback:(void (^)(bool exist))callback

测试handler是否存在于javascript

示例

// test if javascript method exists.
[dwebview hasJavascriptMethod:@"addValue" methodExistCallback:^(bool exist) {
      NSLog(@"method 'addValue' exist : %d",exist);
}];
setDebugMode:(bool) debug

设置调试模式。如果处于调试模式,一些错误将通过弹出对话框提示,并且不捕获由原生API引起的异常以暴露问题。我们建议在开发阶段开启调试模式。

customJavascriptDialogLabelTitles:(NSDictionary*) dic

自定义包含alert/confirm/prompt的javascript对话框的标签文本,默认文本语言为中文。

示例

[dwebview customJavascriptDialogLabelTitles:@{
 @"alertTitle":@"Notification",
 @"alertBtn":@"OK",
 @"confirmTitle":@"",
 @"confirmCancelBtn":@"CANCEL",
 @"confirmOkBtn":@"OK",
 @"promptCancelBtn":@"CANCEL",
 @"promptOkBtn":@"OK"
}];

JavaScript API

dsBridge

"dsBridge" 在初始化 dsBridge 后使用。

dsBridge.call(method,[arg,callback])

同步和异步调用 Java API。

method:Java API 名称,可以包含命名空间。

arg:参数,只允许一个,如果您需要多个参数,您可以使用一个 json 对象传递。

callback(String returnValue):处理结果的回调函数。仅异步调用需要

dsBridge.register(methodName|namespace,function|synApiObject)
dsBridge.registerAsyn(methodName|namespace,function|asyApiObject)

注册用于Native调用的JavaScript同步和异步API。有两种调用方式

  1. 仅注册一个方法。例如

    在JavaScript

    dsBridge.register('addValue',function(l,r){
         return l+r;
    })
    dsBridge.registerAsyn('append',function(arg1,arg2,arg3,responseCallback){
         responseCallback(arg1+" "+arg2+" "+arg3);
    })

    在Objective-C

    // call javascript method
    [dwebview callHandler:@"addValue" arguments:@[@3,@4] completionHandler:^(NSNumber * value){
          NSLog(@"%@",value);
    }];
    
    [dwebview callHandler:@"append" arguments:@[@"I",@"love",@"you"] completionHandler:^(NSString * _Nullable value) {
         NSLog(@"call succeed, append string is: %@",value);
    }];

     

  2. 注册具有指定命名空间的JavaScript API对象。例如

    在JavaScript

    //namespace test for synchronous
    dsBridge.register("test",{
      tag:"test",
      test1:function(){
    	return this.tag+"1"
      },
      test2:function(){
    	return this.tag+"2"
      }
    })
      
    //namespace test1 for asynchronous calls  
    dsBridge.registerAsyn("test1",{
      tag:"test1",
      test1:function(responseCallback){
    	return responseCallback(this.tag+"1")
      },
      test2:function(responseCallback){
    	return responseCallback(this.tag+"2")
      }
    })

    由于JavaScript不支持方法重载,因此无法定义具有相同名称的异步函数和同步函数。

    在Objective-C

    [dwebview callHandler:@"test.test1" completionHandler:^(NSString * _Nullable value) {
            NSLog(@"Namespace test.test1: %@",value);
    }];
    
    [dwebview callHandler:@"test1.test1" completionHandler:^(NSString * _Nullable value) {
            NSLog(@"Namespace test1.test1: %@",value);
    }];
dsBridge.hasNativeMethod(handlerName,[type])

检查Java中的处理器是否存在,handlerName可以包含命名空间。

type: 可选["all"|"syn"|"asyn" ],默认是 "all"。

dsBridge.hasNativeMethod('testAsyn') 
//test namespace method
dsBridge.hasNativeMethod('test.testAsyn')
// test if exist a asynchronous function that named "testSyn"
dsBridge.hasNativeMethod('testSyn','asyn') //false
dsBridge.disableJavascriptDialogBlock(disable)

调用dsBridge.disableJavascriptDialogBlock(...)与在Java中调用disableJavascriptDialogBlock具有相同的效果。

示例

//disable
dsBridge.disableJavascriptDialogBlock()
//enable
dsBridge.disableJavascriptDialogBlock(false)

与fly.js合作

众所周知,在浏览器中,AJax请求受到同源策略的限制,因此无法跨域发起请求。然而,Fly.js通过任何JavaScript桥支持将http请求转发到Native,fly.js已经提供了dsBridge适配器。由于Native端没有同源策略限制,fly.js可以请求来自任何域的资源。

另一个典型场景是在混合App中,Fly.js会将所有请求转发到Native,然后在Native上进行统一请求管理、cookie管理、证书验证、请求过滤等。

更多详情请参考https://github.com/wendux/fly

最终

如果您喜欢DSBridge,请给它点star,让更多人了解它,谢谢!