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,欢迎大家与我一起讨论交流.