//必须给第一个参数前添加下划线"_"来显式忽略参数名。
@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. 这两个方法都有两种调用形式:
1. 注册一个普通的方法,如:
**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);
}];
2. 注册一个对象,指定一个命名空间:
**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);
}];
最后
我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
(NSString * _Nullable value) {
NSLog(@"Namespace test.test1: %@",value);
}];
[dwebview callHandler:@“test1.test1” completionHandler:^(NSString * _Nullable value) {
NSLog(@"Namespace test1.test1: %@",value);
}];
最后
我见过很多技术leader在面试的时候,遇到处于迷茫期的大龄程序员,比面试官年龄都大。这些人有一些共同特征:可能工作了5、6年,还是每天重复给业务部门写代码,工作内容的重复性比较高,没有什么技术含量的工作。问到这些人的职业规划时,他们也没有太多想法。
其实30岁到40岁是一个人职业发展的黄金阶段,一定要在业务范围内的扩张,技术广度和深度提升上有自己的计划,才有助于在职业发展上有持续的发展路径,而不至于停滞不前。
不断奔跑,你就知道学习的意义所在!
[外链图片转存中…(img-OxHOSNwh-1719809320942)]
[外链图片转存中…(img-yNLYn69J-1719809320942)]