WKWebView的使用

911 阅读4分钟

首先创建一个WKWebView对象,同时加载链接

// 注册JS方法
	self.userContentController = [[WKUserContentController alloc] init];
	WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
	configuration.userContentController = self.userContentController;
	[configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"sayHello"];
	
	// 初始化wkwebView
	self.myWbView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
	[self.view addSubview:self.myWbView];
	self.myWbView.UIDelegate = self;
	self.myWbView.navigationDelegate = self;
	

	[self.myWbView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.1.135:8989"]]];

其中configuration是可选, 对应的代理方法

#pragma mark - WKNavigationDelegate
//2. 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
//4. 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
//5. 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
	NSLog(@"方法=%s",__FUNCTION__);
}
// 页面跳转失败的时候调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
	NSLog(@"方法=%s",__FUNCTION__);
}
// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
//3. 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	
	NSLog(@"%@",navigationResponse.response.URL.absoluteString);
	//允许跳转
	decisionHandler(WKNavigationResponsePolicyAllow);
	//不允许跳转
//	decisionHandler(WKNavigationResponsePolicyCancel);
}
//1. 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	
	NSLog(@"%@",navigationAction.request.URL.absoluteString);
	//允许跳转
	decisionHandler(WKNavigationActionPolicyAllow);
	//不允许跳转
//	decisionHandler(WKNavigationActionPolicyCancel);
}

#pragma mark - WKUIDelegate
// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
	NSLog(@"方法=%s",__FUNCTION__);
	return [[WKWebView alloc]init];
}
// 输入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	completionHandler(@"http");
}
// 确认框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	NSLog(@"%@",message);
	completionHandler();
}

#pragma mark - WKScriptMessageHandler
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
	NSLog(@"name =%@,body=%@",message.name,message.body);
}

代理方法的调用顺序依次是以上注释的顺序(网页正确加载) 完整代码:
// MyWKWebVC.h

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>

NS_ASSUME_NONNULL_BEGIN

@interface MyWKWebVC : UIViewController

@end

// 这个类是JS调用OC方法的h中转类,防止强引用无法释放
@interface WeakScriptMessageDelegate : NSObject<WKScriptMessageHandler>

@property (nonatomic, weak) id<WKScriptMessageHandler> scriptDelegate;

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate;

@end

NS_ASSUME_NONNULL_END

// MyWKWebVC.m


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

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

@property(nonatomic, strong) WKWebView *myWbView;

@property(nonatomic, strong) WKUserContentController *userContentController;

@end

@implementation MyWKWebVC

- (void)viewDidLoad {
	[super viewDidLoad];
	// Do any additional setup after loading the view.
	[self setupView];
}
/// 初始化页面
- (void)setupView {
	// 注册JS方法
	self.userContentController = [[WKUserContentController alloc] init];
	WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
	configuration.userContentController = self.userContentController;
	[configuration.userContentController addScriptMessageHandler:[[WeakScriptMessageDelegate alloc] initWithDelegate:self] name:@"sayHello"];
	
	// 初始化wkwebView
	self.myWbView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];
	[self.view addSubview:self.myWbView];
	self.myWbView.UIDelegate = self;
	self.myWbView.navigationDelegate = self;
	

	[self.myWbView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.1.135:8989"]]];
	
	
}

#pragma mark - WKNavigationDelegate
// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation withError:(NSError *)error {
	NSLog(@"方法=%s",__FUNCTION__);
}
// 页面跳转失败的时候调用
- (void)webView:(WKWebView *)webView didFailNavigation:(WKNavigation *)navigation withError:(NSError *)error {
	NSLog(@"方法=%s",__FUNCTION__);
}
// 接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation{
	NSLog(@"方法=%s",__FUNCTION__);
}
// 在收到响应后,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	
	NSLog(@"%@",navigationResponse.response.URL.absoluteString);
	//允许跳转
	decisionHandler(WKNavigationResponsePolicyAllow);
	//不允许跳转
//	decisionHandler(WKNavigationResponsePolicyCancel);
}
// 在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	
	NSLog(@"%@",navigationAction.request.URL.absoluteString);
	//允许跳转
	decisionHandler(WKNavigationActionPolicyAllow);
	//不允许跳转
//	decisionHandler(WKNavigationActionPolicyCancel);
}

#pragma mark - WKUIDelegate
// 创建一个新的WebView
- (WKWebView *)webView:(WKWebView *)webView createWebViewWithConfiguration:(WKWebViewConfiguration *)configuration forNavigationAction:(WKNavigationAction *)navigationAction windowFeatures:(WKWindowFeatures *)windowFeatures{
	NSLog(@"方法=%s",__FUNCTION__);
	return [[WKWebView alloc]init];
}
// 输入框
- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * __nullable result))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	completionHandler(@"http");
}
// 确认框
- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL result))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	completionHandler(YES);
}
// 警告框
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{
	NSLog(@"方法=%s",__FUNCTION__);
	NSLog(@"%@",message);
	completionHandler();
}


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

- (void)dealloc {
	NSLog(@"dealloc-func=%s",__FUNCTION__);
	// 在前面增加的方法一定要remove
	[self.userContentController removeScriptMessageHandlerForName:@"sayHello"];
}

@end

@implementation WeakScriptMessageDelegate

- (instancetype)initWithDelegate:(id<WKScriptMessageHandler>)scriptDelegate {
	self = [super init];
	if (self) {
		self.scriptDelegate = scriptDelegate;
	}
	return self;
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
	[self.scriptDelegate userContentController:userContentController didReceiveScriptMessage:message];
}

@end

对应的html5:

<html>
<head>
    <script>
function say()
{
//前端需要用 window.webkit.messageHandlers.注册的方法名.postMessage({body:传输的数据} 来给native发送消息
    window.webkit.messageHandlers.sayHello.postMessage({body: 'hello world!132'});
}
</script>
</head>
    <body>
        <h1>hello world</h1>
        <button onclick="say()">say hello</button>
    </body>

</html>

参考:
iOS WKWebView导致ViewController不调用dealloc方法
IOS进阶之WKWebView