WKWebView与JS的交互

WKWebView新特性

  • 性能、稳定性、功能大幅度提升
  • 允许JavaScript的Nitro库加载并使用(UIWebView中限制)
  • 支持了更多的HTML5特性
  • 高达60fps的滚动刷新率以及内置手势
  • GPU硬件加速
  • KVO
  • 重构UIWebView成14类与3个协议
一, OC 代码部分
//
//  ViewController.m
//  JS交互
//
//  Created by 张闯 on 16/3/5.
//  Copyright © 2016年张闯的mac pro. All rights reserved.
//

#import "ViewController.h"
#import <WebKit/WebKit.h>

@interface ViewController () <WKScriptMessageHandler, WKNavigationDelegate, WKUIDelegate>

@property (nonatomic,strong) WKWebView *webView;
@property (nonatomic,strong) UIProgressView *progressView;

@end



@implementation ViewController

- (void)viewDidLoad {
    [superviewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.navigationController.navigationBar.translucent = YES;
    
    
    WKWebViewConfiguration *configuretion = [[WKWebViewConfiguration alloc] init];
    WKPreferences *preference = [[WKPreferences alloc] init];
    preference.minimumFontSize = 13;
    preference.javaScriptEnabled = YES;
    configuretion.preferences = preference;
    
    
    // 通过js与webview内容交互配置
    WKUserContentController *contentController = [[WKUserContentController alloc] init];
    configuretion.userContentController = contentController;
    
    //加载时注入js
    //参数一:需要注入的JS语句
    //参数二:注入时间
    //参数三:只添加到mainFrame中为YES
    WKUserScript *script = [[WKUserScript alloc] initWithSource:@"function showAlert() { alert('在载入webview时通过Objective-C注入的JS方法'); }" injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:YES];
    
    [contentController addUserScript:script];
    [contentController addScriptMessageHandler:selfname:@"AppModel"];
    
    
    //初始化webView
    self.webView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuretion];
    //与之交互用到的三大代理:
    //WKNavigationDelegate,与页面导航加载相关
    //WKUIDelegate,与JS交互时的ui展示相关,比较JS的alert、confirm、prompt
    //WKScriptMessageHandler,与js交互相关,通常是iOS端注入名称,js端通过window.webkit.messageHandlers.{NAME}.postMessage()来发消息到iOS端
    self.webView.navigationDelegate =self;
    self.webView.UIDelegate =self;
    
    //加载本地html
    NSURL *url = [[NSBundle mainBundle] URLForResource:@"oc与js交互" withExtension:@"html"];
    [self.webViewloadRequest:[NSURLRequest requestWithURL:url]];
    [self.viewaddSubview:self.webView];
    
    //对于WKWebView,有三个属性支持KVO,因此我们可以监听其值的变化,分别是:loading,title,estimatedProgress,对应功能表示为:是否正在加载中,页面的标题,页面内容加载的进度(值为0.0~1.0)
    [self.webVie waddObserver:self forKeyPath:@"loading" options:NSKeyValueObservingOptionNew context:nil];
    [self.webVie waddObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil];
    [self.webVie waddObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];
    
    self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"back"style:UIBarButtonItemStylePlain target:selfaction:@selector(backAction)];
    
    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"go"style:UIBarButtonItemStylePlain target:selfaction:@selector(goAction)];
    
    
    self.progressView = [[UIProgressView alloc] initWithProgressViewStyle:UIProgressViewStyleDefault];
    self.progressView.frame =CGRectMake(0,64,375,667);
    self.progressView.backgroundColor = [UIColorredColor];
    [self.viewaddSubview:self.progressView];
    
    
    
}

//后退按钮
- (void)backAction{
    
    if (self.webView.goBack) {
        [self.webViewgoBack];
    }
}

//前进按钮
- (void)goAction
{
    if (self.webView.goForward) {
        [self.webViewgoForward];
    }
}

//KVO方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"loading"]) {
        
        NSLog(@"loading");
        [UIApplication sharedApplication].networkActivityIndicatorVisible =YES;
        
    } else if ([keyPath isEqualToString:@"title"]) {
        
        self.title =self.webView.title;
        
    } else if ([keyPath isEqualToString:@"estimatedProgress"]) {
        
        NSLog(@"%f",self.webView.estimatedProgress);
        
        
        [self.progressViewsetProgress:self.webView.estimatedProgress animated:YES];
    }
    
    
    if (!self.webView.loading) {
        NSString *js = @"callJsAlert()";
        [self.webView evaluateJavaScript:jscompletionHandler:^(id_Nullable js, NSError *_Nullable error) {
            NSLog(@"call js alert");
        }];
        
        [UIApplication sharedApplication].networkActivityIndicatorVisible =NO;
        
        [UIView animateWithDuration:1animations:^{
            
            self.progressView.alpha =0.0;
            
        }];
    }
}

#pragma mark - WKUIDelegate

//三种形式的alert

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler
{
    UIAlertController *controller = [UIAlertController alertControllerWithTitle:@"tips" message:messagepreferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK"style:UIAlertActionStyle Defaulthandler:^(UIAlertAction *_Nonnull action) {
        //必须回调completionHandler!!!!!!!!
        completionHandler();
    }];
    
    [controller addAction:action];
    [selfpresentViewController:controlleranimated:YEScompletion:nil];
    
}


- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler
{
    UIAlertController *controller = [UIAlertControlleralert ControllerWithTitle:@"tips"message:@"有个东西出不来啊"preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"OK"style:UIAlertActionStyle Defaulthandler:^(UIAlertAction *_Nonnull action) {
        completionHandler(YES);
    }];
    
    UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"NO"style:UIAlertActionStyle Defaulthandler:^(UIAlertAction *_Nonnull action) {
        completionHandler(NO);
    }];
    
    
    [controller addAction:action1];
    [controller addAction:action2];
    [selfpresentViewController:controlleranimated:YEScompletion:nil];
}


- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString *_Nullable))completionHandler
{
    UIAlertController *controller = [UIAlertController alertControllerWithTitle:promptmessage:defaultTextpreferredStyle:UIAlertControllerStyleAlert];
    [controller addTextFieldWithConfigurationHandler:^(UITextField *_Nonnull textField) {
        textField.backgroundColor = [UIColorredColor];
    }];
    
    UIAlertAction *action = [UIAlertAction actionWithTitle:@"OK"style:UIAlertActionStyle Defaulthandler:^(UIAlertAction *_Nonnull action) {
        
        completionHandler(controller.textFields[0].text);
        
    }];
    [controller addAction:action];
    [selfpresentViewController:controlleranimated:YEScompletion:nil];
    
}

#pragma mark - WKScriptMessageHandler
//通过这个代理方法,就可以得到html文件中js的部分回调给Objective-C的数据

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message
{
    NSLog(@"%@", message.body);
}

#pragma mark - WKNavigationDelegate

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler
{
    NSLog(@"%s",__FUNCTION__);
    
    NSString *string = navigationAction.request.URL.host.lowercaseString;
    NSLog(@"%@", string);
    
    if (navigationAction.navigationType ==WKNavigationTypeLinkActivated &&  [stringcontainsString:@".baidu.com"]) {
        
        [[UIApplication sharedApplication] openURL:navigationAction.request.URL];
        decisionHandler(WKNavigationActionPolicyCancel);
        
    } else {
        
        decisionHandler(WKNavigationActionPolicyAllow);
    }
    
}




二.JS代码部分

<!DOCTYPE html>
<html>
    <head>
        <title>sange and js</title>
        <style type="text/css">
            * {
                font-size: 40px;
            }
        </style>
    </head>
    
    <body>
        
        <div style="margin-top: 100px">
            <h1>Test how to use objective-c call js</h1><br/>
            <div><inputtype="button"value="call js alert"οnclick="callJsAlert()"></div>
            <br/>
            <div><inputtype="button"value="Call js confirm"οnclick="callJsConfirm()"></div><br/>
        </div>
        <br/>
        <div>
            <div><inputtype="button"value="Call Js prompt "οnclick="callJsInput()"></div><br/>
            <div><inputtype="button"value="Objective-C inject js"οnclick="showAlert()"></div><br/>
            <div>Click me here: <a href="http://www.baidu.com">Jump to Baidu</a></div>
        </div>
        
        <br/>
        <div id="SwiftDiv">
            <span id="jsParamFuncSpan"style="color: red; font-size: 50px;"></span>
        </div>
        
        <div onclick = "showJSONData()">
        cilck to show JSON
        </div>
        
        
        <script type="text/javascript">
            
            
            function showJSONData() {
            
            var param = {
                name: "zhangchuang",
                age: "20",
                address: "Shenyang"
            };
            
            window.webkit.messageHandlers.AppModel.postMessage(param);
            
            }
            
            
            function callJsAlert() {
                alert('Objective-C call js to show alert');
            }
        
        function callJsConfirm() {
            if (confirm('confirm','Objective-C call js to show confirm')) {
                document.getElementById('jsParamFuncSpan').innerHTML
                = 'true';
            } else {
                document.getElementById('jsParamFuncSpan').innerHTML
                = 'false';
            }
            
            <!-- window.webkit.messageHandlers.AppModel.postMessage({body: 'call js confirm in js'});-->
        }
        
        function callJsInput() {
            var response = prompt('Hello','Please input your name:');
            document.getElementById('jsParamFuncSpan').innerHTML = response;    
        <!-- window.webkit.messageHandlers.AppModel.postMessage({body: response});-->
        }
        
        // 注意哦,如果JS写错,可能在OC调用JS方法时,都会出错哦。
        var jsParamFunc = function(argument) {
            document.getElementById('jsParamFuncSpan').innerHTML
            = argument['name'];
        }
        showAlert();
            </script>
    </body>
</html>


博主iOS小白一枚,我的微信:656593047,欢迎大家与我一起讨论交流.




  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值