开发者社区> 瓜子三百克> 正文

DSBridge框架使用说明

简介: DSBridge框架使用说明
+关注继续查看

前言


JSBridge VS DSBridge这篇博客对JS交互分析的优缺点相对比较全面(虽然有点自卖自夸😂😂)。之前用过JSBridge,有些PK比较持保留意见哈。由于现在的项目使用的是DSBridge,没有接触过,就对这个框架系统的学习一下吧。

DSBridge源码有了,里面也有使用说明,已经很详细,没必要新增,仅对说明文档黏贴整理学习一下。

Github地址: https://github.com/wendux/DSBridge-IOS


特性

Android、IOS、Javascript 三端易用,轻量且强大、安全且健壮。

同时支持同步调用和异步调用

支持以类的方式集中统一管理API

支持API命名空间

支持调试模式

支持API存在性检测

支持进度回调:一次调用,多次返回

支持Javascript关闭页面事件回调

支持Javascript 模态/非模态对话框

Android端支持腾讯X5内核

安装

pod "dsBridge"

实现四步骤(核心)

步骤一:新建一个类,实现API


#import "dsbridge.h" 
  @implementation JsApiTest
  //同步API 
  - (NSString *) testSyn:(NSString *) msg
  {
      return [msg stringByAppendingString:@"[ syn call]"];
  }
  //异步API
  - (void) testAsyn:(NSString *) msg :(JSCallback)completionHandler
  {
      completionHandler([msg stringByAppendingString:@" [ asyn call]"],YES);
  }
  @end 


可以看到,DSBridge正式通过API类的方式集中、统一地管理API。


步骤二:添加API类实例到 DWKWebView


DWKWebView * dwebview=[[DWKWebView alloc] initWithFrame:bounds];
   // register api object without namespace
   [dwebview addJavascriptObject:[[JsApiTest alloc] init] namespace:nil];


步骤三:在Javascript中调用原生 (Java/Object-c/swift) API ,并注册一个 javascript API供原生调用.


初始化 dsBridge


   

//cdn方式引入初始化代码(中国地区慢,建议下载到本地工程)
     //<script src="https://cdn.jsdelivr.net/npm/dsbridge@3.1.4/dist/dsbridge.js"> //</script>
     //npm方式安装初始化代码
     //npm install dsbridge@3.1.4
     var dsBridge=require("dsbridge")


调用原生API ,并注册一个 javascript API供原生调用.


//同步调用
var str=dsBridge.call("testSyn","testSyn");
//异步调用
dsBridge.call("testAsyn","testAsyn", function (v) {
     alert(v);
})
//注册 javascript API 
dsBridge.register('addValue',function(l,r){
    return l+r;
})


步骤四:在Object-c中调用Javascript API


     

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


OC API 命名注意事项

OC API 必须符合如下签名:


1、同步API.

(id) handler:(id) msg

参数可以是任何类型, 但是返回值类型不能为 void。 如果不需要参数,也必须声明,声明后不使用就行。


如果同步API返回值类型为void,调用时则会导致Crash,请务必遵守签名规范。


2、异步 API.

(void) handler:(id)arg :(void (^)( id result,BOOL complete))completionHandler)

JSCallback 是一个block类型:


 

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

注意:API名字不能以"init"开始,因为oc的类中是被预留的, 如果以"init"开始,执行结果将无法预期(很多时候会crash)。


在Swift中使用

在 Swift中,你应该按照如下方式声明APIs:


//必须给第一个参数前添加下划线"_"来显式忽略参数名。
@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)
}


有两点必须注意:


必须给Swift API添加 “@objc” 标注。

必须给第一个参数前添加下划线"_"来显式忽略参数名

完整的示例在 这里 .


命名空间管理API

命名空间可以帮助你更好的管理API,这在API数量多的时候非常实用,比如在混合应用中。DSBridge (>= v3.0.0) 支持你通过命名空间将API分类管理,并且命名空间支持多级的,不同级之间只需用’.’ 分隔即可。


调试模式设置

在调试模式时,发生一些错误时,将会以弹窗形式提示,并且原生API如果触发异常将不会被自动捕获,因为在调试阶段应该将问题暴露出来。如果调试模式关闭,错误将不会弹窗,并且会自动捕获API触发的异常,防止crash。强烈建议在开发阶段开启调试模式,可以通过如下代码开启调试模式:


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


进度回调

通常情况下,调用一个方法结束后会返回一个结果,是一一对应的。但是有时会遇到一次调用需要多次返回的场景,比如在javascript钟调用端上的一个下载文件功能,端上在下载过程中会多次通知javascript进度, 然后javascript将进度信息展示在h5页面上,这是一个典型的一次调用,多次返回的场景,如果使用其它Javascript bridge, 你将会发现要实现这个功能会比较麻烦,而DSBridge本省支持进度回调,你可以非常简单方便的实现一次调用需要多次返回的场景,下面我们实现一个倒计时的例子:


In Object-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];
    }
}
In javascript
dsBridge.call("callProgress", function (value) {
    document.getElementById("progress").innerText = value
})

完整的示例代码请参考demo工程。


设置Javascript 弹出框样式

DSBridge已经实现了 Javascript的弹出框函数(alert/confirm/prompt),这些对话框按钮、标签文字默认都是中文的,如果你想自定义这些文本可以参考 customJavascriptDialogLabelTitles API,如果你不想使用DSBridge实现的对话框,你可以通过设置DSUIDelegate 属性(是WKUIDelegate的代理属性)完全自定义。

另外注意,DSBridge实现的弹出框都是模态的,这会阻塞UI线程,如果你需要非模态的对话框,请参考disableJavascriptDialogBlock API.


使用DSUIDelegate

在 DWKWebView 中,请使用 DSUIDelegate 代替 UIDelegate , 因为在DWKWebView 内部 UIDelegate已经设置过了,而 DSUIDelegate 正是 UIDelegate 的一个代理。


API 列表说明

Object-C API

在Object-c中我们把实现了供 javascript调用的 API类的实例 成为 Object-c API object:

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

添加一个 Object-c API object 到DWKWebView,并为它指定一个命名空间. 然后,在 javascript 中就可以通过bridge.call("namespace.api",...)来调用Object-c API object中的原生API了。

如果命名空间是空(nil或空字符串), 那么这个添加的 Object-c API object就没有命名空间。在 javascript 通过 bridge.call("api",...)调用。


示例:

In Object-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"];


In 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));
})


通过命名空间名称移除相应的 Object-c API object:

removeJavascriptObject:(NSString *) namespace


OC调用JSAPI:

1、调用 javascript API.methodName 为javascript API 的名称,可以包含命名空间;

2、参数以数组传递,argumentss数组中的元素依次对应javascript API的形参; 3、completionHandler 用于接收javascript API的返回值,注意: completionHandler将在主线程中被执行。

方法:

1、callHandler:(NSString *) methodName arguments:(NSArray *) args

2、callHandler:(NSString *) methodName completionHandler:(void (^)(id value))completionHandler

3、callHandler:(NSString *) methodName arguments:(NSArray *) args completionHandler:(void (^ )(id value))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, confirm, 或 prompt), 那么APP将会挂起,因为这些弹窗都是模态的,会阻塞APP主线程,此时javascript执行流也会阻塞。如果你想避免阻塞,可以通过此API禁止,禁止后,一旦 javascript中调用了这些弹窗函数,APP将弹出非模态对话框,并立即返回,( confirm 会返回 true, prompt 返回空字符串)。

如:


[dwebview disableJavascriptDialogBlock: true]

如果你想恢复模态对话框,传 false 调用即可.


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

当 Javascript中调用window.close时,DWKWebView会触发此监听器:



[dwebview setJavascriptCloseWindowListener:^{
        NSLog(@"window.close called");
}];


hasJavascriptMethod:(NSString*) handlerName methodExistCallback:(void(^)(bool exist))callback:检测是否存在指定的 javascript API,handlerName可以包含命名空间.



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


setDebugMode:(bool) debug:设置调试模式。

在调试模式时,发生一些错误时,将会以弹窗形式提示,并且原生API如果触发异常将不会被自动捕获,因为在调试阶段应该将问题暴露出来。如果调试模式关闭,错误将不会弹窗,并且会自动捕获API触发的异常,防止crash。强烈建议在开发阶段开启调试模式。


customJavascriptDialogLabelTitles:(NSDictionary*) dic

自定义 javascript对话框上按钮、标签的文本,默认的文本语言是中文,你可以自定义英文,如:


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


Javascript API

“dsBridge” 在初始化之后可用 .

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

同步或异步的调用Java API。

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

arg:传递给Java API 的参数。只能传一个,如果需要多个参数时,可以合并成一个json对象参数。

callback(String returnValue): 处理Java API的返回结果. 可选参数,只有异步调用时才需要提供.


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

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

注册同步/异步的Javascript API. 这两个方法都有两种调用形式:


注册一个普通的方法,如:

In Javascript



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


In Object-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);
   }];


注册一个对象,指定一个命名空间:

In 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并不支持函数重载,所以不能在同一个Javascript对象中定义同名的同步函数和异步函数


In Object-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);
   }];

ridge.hasNativeMethod(handlerName,[type])

检测Java中是否存在名为handlerName的API, handlerName 可以包含命名空间.

type: 可选参数,["all"|"syn"|"asyn" ], 默认是 “all”.



//检测是否存在一个名为'testAsyn'的API(无论同步还是异步)
dsBridge.hasNativeMethod('testAsyn') 
//检测test命名空间下是否存在一个’testAsyn’的API
dsBridge.hasNativeMethod('test.testAsyn')
// 检测是否存在一个名为"testSyn"的异步API
dsBridge.hasNativeMethod('testSyn','asyn') //false


dsBridge.disableJavascriptDialogBlock(disable)

调用 dsBridge.disableJavascriptDialogBlock(...) 和在Java中调用 dwebview.disableJavascriptDialogBlock(...) 作用一样.


示例:


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


和 fly.js一起使用

当dsBridge遇见 Fly.js 时,将会打开一个新的世界。fly.js传送门


正如我们所知,在浏览器中,ajax请求受同源策略限制,不能跨域请求资源。然而, Fly.js 有一个强大的功能就是支持请求重定向:将ajax请求通过任何Javascript bridge重定向到端上,并且 Fly.js 官方已经提供的 dsBridge 的 adapter, 可以非常方便的协同dsBridge一起使用。由于端上没有同源策略的限制,所以 fly.js可以请求任何域的资源。


另一个典型的使用场景是在混合APP中,由于Fly.js 可以将所有ajax请求转发到端上,所以,开发者就可以在端上进行统一的请求管理、证书校验、cookie管理、访问控制等。


详情请参考 https://github.com/wendux/fly. (DSBridge Android版 demo中包含fly.js的示例)


版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
20122 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
29511 0
阿里云服务器ECS登录用户名是什么?系统不同默认账号也不同
阿里云服务器Windows系统默认用户名administrator,Linux镜像服务器用户名root
16730 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
20893 0
腾讯云服务器 设置ngxin + fastdfs +tomcat 开机自启动
在tomcat中新建一个可以启动的 .sh 脚本文件 /usr/local/tomcat7/bin/ export JAVA_HOME=/usr/local/java/jdk7 export PATH=$JAVA_HOME/bin/:$PATH export CLASSPATH=.
14909 0
阿里云服务器怎么设置密码?怎么停机?怎么重启服务器?
如果在创建实例时没有设置密码,或者密码丢失,您可以在控制台上重新设置实例的登录密码。本文仅描述如何在 ECS 管理控制台上修改实例登录密码。
23609 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
22398 0
131
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
JS零基础入门教程(上册)
立即下载
性能优化方法论
立即下载
手把手学习日志服务SLS,云启实验室实战指南
立即下载