WolfAvenue 发表于 2021-6-9 11:56

WebViewJavascriptBridge APP与H5交互

现在H5能调用APP的方法这个样子
scan 是app 那边定义好了的方法
window.WebViewJavascriptBridge.callHandler("scan", {}, function (imgDataBase64) {
         
      });

请问,H5页面如何定义函数给APP调用,我看网上使用的是window.WebViewJavascriptBridge.registerHanlder 函数注册
但是registerHanlder 是未定义,registerHanlder 函数需要APP提供吗?

liesauer 发表于 2021-6-9 14:39

目前ios已经不让用uiwebview了,所以WebViewJavascriptBridge也不推荐使用了,原生调H5其实很简单,本质就是调用JS而已,给你参考下我的做法吧

#pragma mark - JS 交互
- (void)JSInvoke:(NSString *)function params:(NSDictionary *)params callback:(void (^)(NSDictionary *result, NSDictionary *params))callback {
    NSString *paramsStr = params ? : @"null";
    if (!callback) {
      return callback:nil];
    }
    WKWebView *webview = self.webViews[];
    if (webview) {
      NSString *token = [ UUIDString];
      NSString *code = ;
      self.callbacks = ;
      dispatch_async(dispatch_get_main_queue(), ^{
            [webview evaluateJavaScript:code completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                if (error) {
                  NSLog(@"异常发生%@", error);
                }
            }];
      });
    }
}

- (void)runJS:(NSString *)code on:(NSString *)token callback:(void(^)(NSDictionary *result, NSDictionary *params))callback {
    if (!token) {
      token = ;
    }
    WKWebView *webview = self.webViews;
    if (webview) {
      NSString *token = [ UUIDString];
      if (callback) {
            self.callbacks = ;
            code = ;
      }
      dispatch_async(dispatch_get_main_queue(), ^{
            [webview evaluateJavaScript:code completionHandler:^(id _Nullable result, NSError * _Nullable error) {
                if (error) {
                  NSLog(@"异常发生%@", error);
                }
            }];
      });
    }
}

- (void)runJS:(NSString *)code callback:(void(^)(NSDictionary *result, NSDictionary *params))callback {
    return callback:callback];
}

liesauer 发表于 2021-6-9 14:54

顺便解释一下代码中的部分含义,我们的App是使用了多个WKWebView模拟电脑的Tab页概念的,所以在代码中你会看到多处或者self.webViews,这是为了获取最顶层或特定层的WebView(网页),并在其中执行想执行的JS代码,并且每次的Hybrid交互都会有一个唯一token指示,整个交互流程就是:
1. JS调原生,封装一个调用原生xxx的JS函数->调用一个封装好的nativeInvoke方法->调用postMessage->原生收到message->调用原生方法->原生执行JS代码(nativeInvokeFinished)
2. 原生调JS,封装一个调用JSxxx的原生方法->调用一个封装好的JSInvoke方法->调用封装好的runJS方法->调用wkwebview的evaluateJavaScript方法->执行对应的JS函数并调用JSInvokeFinished方法

WolfAvenue 发表于 2021-6-9 14:55

liesauer 发表于 2021-6-9 14:39
目前ios已经不让用uiwebview了,所以WebViewJavascriptBridge也不推荐使用了,原生调H5其实很简单,本质就 ...

objective-c语法好怪异哦,APP开发不太懂,能直接调用js 中的全局对象吗? 如果我在js window对象上定义好几个函数(window.js定义的函数名()),objective-c能直接调用吗?

liesauer 发表于 2021-6-9 15:00

WolfAvenue 发表于 2021-6-9 14:55
objective-c语法好怪异哦,APP开发不太懂,能直接调用js 中的全局对象吗? 如果我在js window对象上定义 ...

可以的,本质上所有原生调JS的操作,都是通过evaluateJavaScript方法完成的,你传过去的代码只要是任意合法的JS代码就行

WolfAvenue 发表于 2021-6-9 15:10

liesauer 发表于 2021-6-9 15:00
可以的,本质上所有原生调JS的操作,都是通过evaluateJavaScript方法完成的,你传过去的代码只要是任意合 ...

那这个window.WebViewJavascriptBridge 对象是uiwebview 提供的么,这样看来看能自定义其他对象代替window.WebViewJavascriptBridge 功能把。目前 window.WebViewJavascriptBridge.callHandler函数有定义,registerHanlder 函数没定义,没看懂,原生也能定义js对象吧?

liesauer 发表于 2021-6-9 15:18

肯定可以啊,它只是封装了足够多的细节而已,让你看起来好像原生、JS能直接互相调用,但最终的本质都是离不开执行JS代码的,所以你完完全全可以在原生这边通过evaluateJavaScript方法来做到定义变量、定义方法函数、执行方法函数、赋值、取值,evaluateJavaScript方法就是让你写JS代码的!所以你写window.aaa = 100,又或者是window.test = () => console.log('test'),或者是window.test2(window.aaa),任意的JS代码都是可以的

debug_cat 发表于 2021-6-9 23:30

我今天才和web调试了,不知道你问的是ios还是安卓端,我知道安卓如何相互通信,ios没研究

WolfAvenue 发表于 2021-6-10 09:13

莫问刀 发表于 2021-6-9 23:30
我今天才和web调试了,不知道你问的是ios还是安卓端,我知道安卓如何相互通信,ios没研究

安卓端的是如何通信的,用WebViewJavascriptBridge这个吗?web端如何定义函数,安卓端调用js函数

debug_cat 发表于 2021-6-10 15:49

WolfAvenue 发表于 2021-6-10 09:13
安卓端的是如何通信的,用WebViewJavascriptBridge这个吗?web端如何定义函数,安卓端调用js函数

我调试成功的是根据这个帖子成功的。https://www.jianshu.com/p/345f4d8a5cfa
页: [1]
查看完整版本: WebViewJavascriptBridge APP与H5交互