首先创建一个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