美文网首页
VUE 与 原生交互(iOS为主)

VUE 与 原生交互(iOS为主)

作者: 等不来的期待 | 来源:发表于2023-10-18 16:29 被阅读0次

使用WKWebView的时候,如果想要实现JS调用OC方法,除了拦截URL之外,还有一种简单的方式。那就是利用WKWebView的新特性MessageHandler来实现JS调用原生方法。

MessageHandler 是什么?

WKWebView 初始化时,有一个参数叫configuration,它是WKWebViewConfiguration类型的参数,而WKWebViewConfiguration有一个属性叫userContentController,它又是WKUserContentController类型的参数。WKUserContentController对象有一个方法- addScriptMessageHandler:name:,我把这个功能简称为MessageHandler。

  • addScriptMessageHandler:name:有两个参数,第一个参数是userContentController的代理对象,第二个参数是JS里发送postMessage的对象。 所以要使用MessageHandler功能,就必须要实现WKScriptMessageHandler协议。 我们在该API的描述里可以看到在JS中的使用方法:
window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
//其中<name>,就是上面方法里的第二个参数`name`。
//例如我们调用API的时候第二个参数填@"Share",那么在JS里就是:
//window.webkit.messageHandlers.Share.postMessage(<messageBody>)
//<messageBody>是一个键值对,键是body,值可以有多种类型的参数。
// 在`WKScriptMessageHandler`协议中,我们可以看到mssage是`WKScriptMessage`类型,有一个属性叫body。
// 而注释里写明了body 的类型:
Allowed types are NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull.

MessageHandler的使用

// 这是创建configuration 的过程
    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    WKPreferences *preferences = [WKPreferences new];
    preferences.javaScriptCanOpenWindowsAutomatically = YES;
    preferences.minimumFontSize = 40.0;
    configuration.preferences = preferences;
    

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // addScriptMessageHandler 很容易导致循环引用
    // 控制器 强引用了WKWebView,WKWebView copy(强引用了)configuration, configuration copy (强引用了)userContentController
    // userContentController 强引用了 self (控制器)
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"GoBack"];
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"Share"];
}
//需要注意的是addScriptMessageHandler很容易引起循环引用,导致控制器无法被释放,所以需要加入以下这段:
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    // 因此这里要记得移除handlers
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"Shake"];
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"GoBack"];
}

WKScriptMessageHandler的代理实现

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
//    message.body  --  Allowed types are NSNumber, NSString, NSDate, NSArray,NSDictionary, and NSNull.
  if ([message.name isEqualToString:@"Shake"]) {
         NSLog(@"分享");
    } else if ([message.name isEqualToString:@"GoBack"]) {
         NSLog(@"返回");
    }
}

JS调iOS原生方法

const u = navigator.userAgent;
//android终端
const isAndroid = u.indexOf('Android') > -1 || u.indexOf('Adr') > -1;
// IOS终端
const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);

 if (isiOS) {<!-- -->
  window.webkit.messageHandlers.GoBack.postMessage('');//getUserId.postMessage('')为IOS定义的原生方法
 //你的逻辑代码
 } else if (isAndroid) {<!-- -->
  window.java_obj.GoBack() //java_obj.getUserId()为安卓定义的方法,具体方法名可与其沟通
 // 你的逻辑代码
 }

相关文章

网友评论

      本文标题:VUE 与 原生交互(iOS为主)

      本文链接:https://www.haomeiwen.com/subject/lfjcidtx.html