美文网首页
WKWebView与JS交互

WKWebView与JS交互

作者: 黑化肥发灰 | 来源:发表于2018-02-28 17:46 被阅读86次

1. 首先介绍几个概念

WKScriptMessageHandler

WebKit库中有个代理WKScriptMessageHandler就是专门来做交互的,它能让网页通过JS把消息发送给OC,其中协议方法如下

@protocol WKScriptMessageHandler <NSObject>

@required

/*! @abstract Invoked when a script message is received from a webpage.
 @param userContentController The user content controller invoking the
 delegate method.
 @param message The script message received.
 */
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;

@end

从协议中可以看出使用了两个类WKUserContentController和WKScriptMessage。WKUserContentController可以理解为调度器,WKScriptMessage则是携带的数据。

WKUserContentController 内容交互控制器

我们要通过webview与JS进行交互,就需要用到这个类,它是用于让JS注入对象的,注入对象后,JS端就可以使用这个方法。它的所有属性及方法说明如下:

// 只读属性,所有添加的WKUserScript都在这里可以获取到
@property (nonatomic, readonly, copy) NSArray<WKUserScript *> *userScripts;
 
// 注入JS,即向网页中注入我们的JS方法,这是一个非常强大的功能,开发中要慎用。
- (void)addUserScript:(WKUserScript *)userScript;
 
// 移除所有注入的JS
- (void)removeAllUserScripts;
 
// 添加scriptMessageHandler到所有的frames中,则都可以通过
// window.webkit.messageHandlers.<name>.postMessage(<messageBody>)
// 发送消息
// 比如,JS要调用我们原生的方法,就可以通过这种方式了
// 添加JS调用OC的桥梁,这里的name对应 WKScriptMessage中的name。
- (void)addScriptMessageHandler:(id <WKScriptMessageHandler>)scriptMessageHandler name:(NSString *)name;
 
// 根据name移除所注入的scriptMessageHandler
- (void)removeScriptMessageHandlerForName:(NSString *)name;

WKScriptMessage

WKScriptMessage 就是 JS 通知OC的数据,其中有两个核心,name 和 body。

@interface WKScriptMessage : NSObject

/*! @abstract The body of the message.
 @discussion Allowed types are NSNumber, NSString, NSDate, NSArray,
 NSDictionary, and NSNull.
 */
@property (nonatomic, readonly, copy) id body;

/*! @abstract The web view sending the message. */
@property (nullable, nonatomic, readonly, weak) WKWebView *webView;

/*! @abstract The frame sending the message. */
@property (nonatomic, readonly, copy) WKFrameInfo *frameInfo;

/*! @abstract The name of the message handler to which the message is sent.
 */
@property (nonatomic, readonly, copy) NSString *name;

@end

WKUserScript

在WKUserContentController中,使用到WKUserScript。WKUserContentController是用于与JS交互的类,而所注入的JS是WKUserScript对象,它的所有属性和方法如下:

// JS源代码
@property (nonatomic, readonly, copy) NSString *source;
 
// JS注入时间
@property (nonatomic, readonly) WKUserScriptInjectionTime injectionTime;
 
// 只读属性,表示JS是否应该注入到所有的frames中还是只有main frame.
@property (nonatomic, readonly, getter=isForMainFrameOnly) BOOL forMainFrameOnly;
 
// 初始化方法,用于创建WKUserScript对象
// source:JS源代码
// injectionTime:JS注入的时间
// forMainFrameOnly:是否只注入main frame
- (instancetype)initWithSource:(NSString *)source injectionTime:(WKUserScriptInjectionTime)injectionTime forMainFrameOnly:(BOOL)forMainFrameOnly;

2. JS 调用 OC

iOS端配置代码如下:

config.userContentController = [[WKUserContentController alloc] init];
 
// 注入JS对象名称senderModel,当JS通过senderModel来调用时,我们可以在WKScriptMessageHandler代理中接收到
[config.userContentController addScriptMessageHandler:self name:@"senderModel"];

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController
      didReceiveScriptMessage:(WKScriptMessage *)message {
  if ([message.name isEqualToString:@"senderModel"]) {
    // 打印所传过来的参数,只支持NSNumber, NSString, NSDate, NSArray,
    // NSDictionary, and NSNull类型
    //do something
    NSLog(@"%@", message.body);
  }
}

这里面senderModel就是我们要注入的名称,注入之后,就可以在JS端调用了,传数据统一通过body来传递,类型可以随,但是只支持OC的一些类型(NSNumber, NSString, NSDate, NSArray, NSDictionary, and NSNull类型)

JS端代码如下:

    <script type="text/javascript">
      function callJsAlert() {
        alert('Please show alert');    
        window.webkit.messageHandlers.senderModel.postMessage({body: 'Alert'});
      }
    </script>

3. OC 调用 JS

OC调用JS特别简单,只需要 WKWebView 调用下面方法即可。

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ __nullable)(__nullable id, NSError * __nullable error))completionHandler;

如下

- (void)buttonTap
{
    NSString *str = @"OC 调用 JS";
    [self.webView evaluateJavaScript:[NSString stringWithFormat:@"onCallJS('%@')", str] completionHandler:^(id _Nullable data, NSError * _Nullable error) {
        if (error) {
            NSLog(@"错误:%@", error.localizedDescription);
        }
    }];
}

OC将通知发送给JS后,JS要响应这个onCallJS方法。在html文件中添加 onCallJS方法

 function onCallJS(params) {
     document.getElementById('jsParamFuncSpan').innerHTML = params;
}

4. demo链接 WKWebViewDemo

相关文章

网友评论

      本文标题:WKWebView与JS交互

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