WKWebView与JS交互

首先要在使用的地方引入WebKit#import

初始化

WKWebView有一个指定初始化方法:

/*! @abstract Returns a web view initialized with a specified frame and
 configuration.
 @param frame The frame for the new web view.
 @param configuration The configuration for the new web view.
 @result An initialized web view, or nil if the object could not be
 initialized.
 @discussion This is a designated initializer. You can use
 @link -initWithFrame: @/link to initialize an instance with the default
 configuration. The initializer copies the specified configuration, so
 mutating the configuration after invoking the initializer has no effect
 on the web view.
 */


- (instancetype)initWithFrame:(CGRect)frame configuration:(WKWebViewConfiguration *)configuration NS_DESIGNATED_INITIALIZER;

这个方法里的configuration可以配置很多东西,比如配置js是否支持等等。它有一个属性userContentController,后面讲的OC和JS交互,以及诸如js代码都会用到它。

JS调用OC的方法

1.拦截URL
html的代码:



    
        
        
        
        
        
        分享页
    
    
        

当用户点击按钮时,会在WKWebview的代理方法:

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
    NSURLRequest *request = [navigationAction request];
    NSString * scheme = request.URL.scheme;
    NSString * host = request.URL.host;
    NSString * query = request.URL.query;
    if ([scheme isEqualToString:@"test1"]) {
        NSString *methodName = host;
        if (query) {
            methodName = [methodName stringByAppendingString:@":"];
        }
        SEL sel = NSSelectorFromString(methodName);
        NSString *parameter = [[query componentsSeparatedByString:@"="] lastObject];
        [self performSelector:sel withObject:parameter];
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
        
    }else if ([scheme isEqualToString:@"test2"]){//JS中的是Test2,在拦截到的url scheme全都被转化为小写。
        NSURL *url = request.URL;
        NSArray *params =[url.query componentsSeparatedByString:@"&"];
        NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];
        for (NSString *paramStr in params) {
            NSArray *dicArray = [paramStr componentsSeparatedByString:@"="];
            if (dicArray.count > 1) {
                NSString *decodeValue = [dicArray[1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
                [tempDic setObject:decodeValue forKey:dicArray[0]];
            }
        }
        
        
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"方式一" message:@"这是OC原生的弹出窗" delegate:self cancelButtonTitle:@"收到" otherButtonTitles:nil];
        [alertView show];
        NSLog(@"tempDic:%@",tempDic);
        decisionHandler(WKNavigationActionPolicyCancel);
        return;
    }
    decisionHandler(WKNavigationActionPolicyAllow);
}

2.scriptMessageHandler
这是Apple在WebKit里新增加的方法,位于WKUserContentController类里。

/*! @abstract Adds a script message handler.
 @param scriptMessageHandler The message handler to add.
 @param name The name of the message handler.
 @discussion Adding a scriptMessageHandler adds a function
 window.webkit.messageHandlers..postMessage() for all
 frames.
 */
- (void)addScriptMessageHandler:(id )scriptMessageHandler name:(NSString *)name;

/*! @abstract Removes a script message handler.
 @param name The name of the message handler to remove.
 */
- (void)removeScriptMessageHandlerForName:(NSString *)name;

第一个方法会在所有的frame里添加一个js的函数window.webkit.messageHandlers..postMessage()。比如,我们在OC中添加一个handle:
[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"shareNothing"];
当我们在js中调用下面方法时:
window.webkit.messageHandlers.shareNothing.postMessage(null);//null必须要写
我们在OC中会收到WKScriptMessageHandler的回调:

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    if ([message.name isEqualToString:@"shareNothing"]) {
    }
}

当然,记得在适当的地方调用removeScriptMessageHandler:

[_webView.configuration.userContentController removeScriptMessageHandlerForName:@"shareNothing"];

html代码:



    
        
        
        
        
        
        分享页
    
    
        

OC代码:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [_webView.configuration.userContentController addScriptMessageHandler:self name:@"shareTitle"];
    [_webView.configuration.userContentController addScriptMessageHandler:self name:@"shareNothing"];
}

- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"shareTitle"];
    [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"shareNothing"];
}

#pragma mark -- WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    NSString *name = message.name;
    id body = message.body;
    NSLog(@"%@", message.name);
    NSLog(@"%@", message.body);
    
    if ([name isEqualToString:@"shareTitle"]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"成功" message:@"JS调用OC代码成功!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
    
    if ([name isEqualToString:@"shareNothing"]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"成功" message:@"JS调用OC代码成功!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
}

3.JS对象:
html代码:



    
        
        
        
    
    
        

        

html中用到了JSObject,这里oc里要添加自定义的脚本:

/**
 * Native为H5提供的Api接口
 *
 * @type {js对象}
 */
var JSObject = (function() {

    var NativeApi = {
        share: function(param) {
            //调用native端
            _nativeShare(param);
        },
    }
    function _nativeShare(param) {
        //js -> oc
        window.webkit.messageHandlers.shareTitle.postMessage(param);
    }

    //闭包,把Api对象返回
    return NativeApi;
})();

OC的代码:

- (void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    [self addNativeApiToJS];

}
- (void)viewWillDisappear:(BOOL)animated{
    [super viewWillDisappear:animated];
    [_webView.configuration.userContentController removeScriptMessageHandlerForName:@"shareTitle"];
}
- (void)addNativeApiToJS
{
    //防止频繁IO操作,造成性能影响
    static NSString *nativejsSource;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        nativejsSource = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"NativeApi" ofType:@"js"] encoding:NSUTF8StringEncoding error:nil];
    });
    //添加自定义的脚本
    WKUserScript *js = [[WKUserScript alloc] initWithSource:nativejsSource injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    [self.webView.configuration.userContentController addUserScript:js];
    //注册回调
    [self.webView.configuration.userContentController addScriptMessageHandler:self name:@"shareTitle"];
}

#pragma mark -- WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    
    NSString *name = message.name;
    id body = message.body;
    NSLog(@"%@", message.name);
    NSLog(@"%@", message.body);
    
    if ([name isEqualToString:@"shareTitle"]) {
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"成功" message:@"JS调用OC代码成功!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];
        [alert show];
    }
    
}

你可能感兴趣的:(WKWebView与JS交互)