DSBridge在项目中实现跨平台交互

前言

公司的客户有许多传统行业,他们的需求有绝大多数是OA办公模块。针对比较简单的业务,例如:请假申请,出差申请等。为了节省开发成本,使用H5版本开发,节省开发成本,但有些功能可能涉及到调用原生的功能(好比陀螺仪,录音),或者H5比较困难实现的功能。
javascript

功能

Vue+VantUI进行H5的开发,同时使用 DSBridge 进行交互。
html

注意点

以前iOS使用的版本是2.0.6版本,使用 DUIWebView 去加载的页面,由于选图的组件使用的是原生,要解决跨域问题。固然这是很差的方案。首先不安全,其次,后来有客户反映,iOS12以后,加载部分页面后,界面就卡死了。以后就升级到最新的版本3.0.6,升级到 DWKWebView,选图的功能暂时是把图片转成Base64字符串,加上 data:image/png;base64, 协议,提供给img 标签使用。java

具体使用

LKH5ContentViewController

加载H5内容的容器git

@property (strong, nonatomic) DWKWebView *webview;
@property (strong, nonatomic) LKH5Api *h5Api;

self.webview.navigationDelegate = self;
[self.webview addJavascriptObject:self.h5Api namespace:nil];

#pragma mark - WKNavigationDelegate
复制代码

LKH5Api

提供全部原生API的工具github

同步获取原生的数据
- (NSString *)getSyncMobileBase:(NSDictionary *)args{
// args 是 H5 端传过来的参数
    NSDictionary *params = CURRENTUSER.jwt ? : @{};
    NSMutableDictionary *baseInfo = [NSMutableDictionary dictionary];
   baseInfo[@"jwt"] = params;
   baseInfo[@"appurl"] = @""
   baseInfo[@"ip"] = @"";
   baseInfo[@"port"] = @"";
   return [baseInfo mj_JSONString];
}
复制代码

异步获取原生的数据

- (void)getMobileBase:(NSDictionary *)args :(JSCallback)handler{
// args 是 H5 端传过来的参数
    dispatch_async(dispatch_get_main_queue(), ^{
        NSDictionary *params = CURRENTUSER.jwt ? : @{};
        NSMutableDictionary *baseInfo = [NSMutableDictionary dictionary];
        baseInfo[@"jwt"] = params;
        baseInfo[@"appurl"] = @"";
        baseInfo[@"ip"] = @"";
        baseInfo[@"port"] = @"";
        handler([baseInfo mj_JSONString],YES);
    });
    
}
复制代码

H5端调用

<!DOCTYPE html>
...
<body>
<button id="getMobileBase" type="button" onclick="getMobileBase()">获取MobileBase</button>

<script type="text/javascript">

    function getMobileBase() {
        LKBridge.getMobileBase({
         complete:function(jsonStr){
              document.getElementById('getMobileBase').innerHTML = jsonStr
         }
        })
    }
</script>
</body>
</html>
复制代码

在Native 中调用JS API

[self.webview callHandler:@"registerMobileBase" arguments:@[[baseInfo mj_JSONString]] completionHandler:^(NSString * value){
        HTLog(@"%@",value);
    }];
复制代码

LKBridge 是咱们中转的一层,主要实现 dsBridge 调用原生的API的过程。web

window.LKBridge = {
    getMobileBase:function(obj) {
        dsBridge.call('getMobileBase', obj.complete);
    }
}
复制代码

效果

其余

如果简单的交互,也能够经过截取此url,与js交互。
使用场景:好比加载 echarts 柱状图,点击某根柱子,调整具体的原生的VC页面。json

<!DOCTYPE html>
<html>
...
window.location.href='luculent:'+mNoArr[param.dataIndex]+'||'+titleArr[param.dataIndex];
</html>
复制代码
WKWebViewDelegate
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    //将url转换为string
    NSString *requestString = [[navigationAction.request URL] absoluteString];
   //hasPrefix 判断建立的字符串内容是否以luculent:字符开始
   if ([requestString hasPrefix:@"luculent:"]){
        decisionHandler(WKNavigationActionPolicyCancel);
   }else {
        decisionHandler(WKNavigationActionPolicyAllow);
    }
}
复制代码
UIWebViewDelegate
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    NSString *requestString = [[[request URL] absoluteString]stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    if ([[requestString componentsSeparatedByString:@":"].firstObject isEqualToString:@"luculent"]) {
        ...
        return NO; 
    }
    return YES;
}
复制代码