一、版本
8系统前,用UIWebView
8系统后,用webkit,WKWebView
因为webkit有两大优点:
1、占用内存更小,
2、可以通过回调直接捕捉网页上的alert,输入等js操作
二、代码
第一部分:UIViewController
//
// ViewController.m
// WKWebView
//
// Created by nnandzc on 16/11/6.
// Copyright © 2016
年
nnandzc. All rights reserved.
//
#import
"ViewController.h"
#import
<JavaScriptCore/JavaScriptCore.h>
#import
<WebKit/WebKit.h>
@interface
ViewController
()
<
WKUIDelegate
,
WKNavigationDelegate
,
WKScriptMessageHandler
>
@property
(
nonatomic
,
strong
)
WKWebView
*webView;
@property
(
nonatomic
,
strong
,
readonly
)
JSContext
*jsContext;
@end
@implementation
ViewController
- (
void
)viewDidLoad {
[
super
viewDidLoad
];
[
self
webView
];
}
- (
WKWebView
*)webView
{
if
(!
_webView
)
{
// js
配置
WKUserContentController
*userContentController = [[
WKUserContentController
alloc
]
init
];
[userContentController
addScriptMessageHandler
:
self
name
:
@"jsCallOC"
];
// WKWebView
的配置
WKWebViewConfiguration
*configuration = [[
WKWebViewConfiguration
alloc
]
init
];
configuration.
userContentController
= userContentController;
_webView
= [[
WKWebView
alloc
]
initWithFrame
:
self
.
view
.
bounds
configuration
:configuration];
_webView
.
navigationDelegate
=
self
;
_webView
.
UIDelegate
=
self
;
[
_webView
addObserver
:
self
forKeyPath
:
@"estimatedProgress"
options
:
NSKeyValueObservingOptionNew
context
:
nil
];
NSString
*path = [[
NSBundle
mainBundle
]
bundlePath
];
NSURL
*baseURL = [
NSURL
fileURLWithPath
:path];
NSString
* htmlPath = [[
NSBundle
mainBundle
]
pathForResource
:
@"index1"
ofType
:
@"html"
];
NSString
* htmlCont = [
NSString
stringWithContentsOfFile
:htmlPath
encoding
:
NSUTF8StringEncoding
error
:
nil
];
[
self
.
webView
loadHTMLString
:htmlCont
baseURL
:baseURL];
// [_webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
[
self
.
view
addSubview
:
_webView
];
}
return
_webView
;
}
-(
void
)observeValueForKeyPath:(
NSString
*)keyPath ofObject:(
id
)object change:(
NSDictionary
<
NSString
*,
id
> *)change context:(
void
*)context
{
if
(object ==
_webView
&& [keyPath
isEqualToString
:
@"estimatedProgress"
] ) {
//
这里就不写进度条了,把加载的进度打印出来,进度条可以自己加上去!
CGFloat
newProgress = [[change
objectForKey
:
NSKeyValueChangeNewKey
]
floatValue
];
NSLog
(
@"%f"
,newProgress);
}
}
//
页面开始加载时调用
- (
void
)webView:(
WKWebView
*)webView didStartProvisionalNavigation:(
WKNavigation
*)navigation
{
// NSLog(@"%s", __func__);
}
//
当内容开始返回时调用
- (
void
)webView:(
WKWebView
*)webView didCommitNavigation:(
WKNavigation
*)navigation
{
// NSLog(@"%s", __func__);
}
//
页面加载完成之后调用
- (
void
)webView:(
WKWebView
*)webView didFinishNavigation:(
WKNavigation
*)navigation
{
// _jsContext = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
[
_webView
evaluateJavaScript
:
@"navigator.userAgent"
completionHandler
:^(
id
_Nullable
string,
NSError
*
_Nullable
error) {
NSLog
(
@"string = %@"
, string);
}];
}
//
页面加载失败时调用
- (
void
)webView:(
WKWebView
*)webView didFailProvisionalNavigation:(
WKNavigation
*)navigation
{
// NSLog(@"%s", __func__);
}
//
接收到服务器跳转请求之后调用
- (
void
)webView:(
WKWebView
*)webView didReceiveServerRedirectForProvisionalNavigation:(
WKNavigation
*)navigation
{
// NSLog(@"%s", __func__);
}
//
在收到响应后,决定是否跳转
- (
void
)webView:(
WKWebView
*)webView decidePolicyForNavigationResponse:(
WKNavigationResponse
*)navigationResponse decisionHandler:(
void
(^)(
WKNavigationResponsePolicy
))decisionHandler
{
// NSLog(@"%s", __func__);
decisionHandler(
WKNavigationResponsePolicyAllow
);
}
//
在发送请求之前,决定是否跳转
- (
void
)webView:(
WKWebView
*)webView decidePolicyForNavigationAction:(
WKNavigationAction
*)navigationAction decisionHandler:(
void
(^)(
WKNavigationActionPolicy
))decisionHandler
{
// NSLog(@"%s", __func__);
decisionHandler(
WKNavigationActionPolicyAllow
);
}
-(
void
)webView:(
WKWebView
*)webView runJavaScriptAlertPanelWithMessage:(
NSString
*)message initiatedByFrame:(
WKFrameInfo
*)frame completionHandler:(
void
(^)(
void
))completionHandler
{
UIAlertController
*alert = [
UIAlertController
alertControllerWithTitle
:
@"alert"
message
:
@"JS
调用
alert"
preferredStyle
:
UIAlertControllerStyleAlert
];
[alert
addAction
:[
UIAlertAction
actionWithTitle
:
@"
确定
"
style
:
UIAlertActionStyleDefault
handler
:^(
UIAlertAction
*
_Nonnull
action) {
}]];
[
self
presentViewController
:alert
animated
:
YES
completion
:
NULL
];
completionHandler();
NSLog
(
@"%@"
, message);
}
-(
void
)webView:(
WKWebView
*)webView runJavaScriptTextInputPanelWithPrompt:(
NSString
*)prompt defaultText:(
NSString
*)defaultText initiatedByFrame:(
WKFrameInfo
*)frame completionHandler:(
void
(^)(
NSString
*
_Nullable
))completionHandler
{
}
-(
void
)webView:(
WKWebView
*)webView runJavaScriptConfirmPanelWithMessage:(
NSString
*)message initiatedByFrame:(
WKFrameInfo
*)frame completionHandler:(
void
(^)(
BOOL
))completionHandler
{
}
@end
第二部分:
index1.js
function
hello(){
alert(
"hello"
);
}
第三部分:index1.css
#p{
color
:
red
;
}
#img{
width
:
120
px
;
height
:
50
px
;
}
#a{
color
:
yellow
;
}
第四部分:index1.html
<!DOCTYPE html>
<html>
<head
lang
=
"zh"
>
<meta
charset
=
"UTF-8"
>
<title>
第一个
HTML
</title>
<link
rel
=
"stylesheet"
type
=
"text/css"
href
=
"index1.css"
>
<script
type
=
"text/javascript"
src
=
"index1.js"
></script>
</head>
<body>
<h1>
我是
HTML
</h1>
<p
id
=
"p"
>
p
标签
</p>
<img
id
=
"img"
src
=
"image.png"
alt
=
"
百度
LOGO"
><br/>
<a
id
=
"a"
href
=
"[http://baidu.com]()"
>
我要到百度
</a>
<br/><br/><br/>
<button
onclick
=
"hello()"
>
点击我弹出
hello
</button>
<input
type
=
"button"
value
=
"
测试
log"
onclick
=
"activityList({'tytyty':'hehe'})"
/>
</body>
</html>
三、总结:以上代码解决了
1、网页、自定义html内容加载
2、加载过程中的回调操作
3、对于已经webkit已经替我们做好事件响应链的几个操作的回调:网页弹出alert,网页输入文字等
4、如果想通过web端调用OC端,则通过WKNavigation中的request属性,截获到服务端的请求,客户端可以和服务端约定好字符串,截获到这一段字符串时,客户端就可以为匹配字符串定义操作。参数也可以通过字符串传递给客户端
5、获取网页元素属性,和UIWebView一样,也是执行一个类似evaluateJavascript的方法,只不过WKWebView是block形式的,UIWebView是返回值形式的