wkwebview与js通信学习总结(三) 之例子

本文介绍如何使用WKWebView实现在iOS应用中JavaScript与Objective-C的双向通信,包括配置WKWebView、设置JS调用Native及Native调用JS的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  • 首先准备一份html的文件,并且导入到工程中,内容如下:

<html>
    <head>
        <meta charset="utf-8" />
        <style>
       body {
                background-color: #d0e4fe;
            }
        
        h4 {
            color: orange;
            text-align: left;
            font-family: "Thimes New Roman";
            font-size: 20px;
        }
        </style>
    </head>
    
    <body>
        <input type="text" />
        <h4> 用户名 </h4>
        <input type="text" />
        <h4> 密码 </h4>
        <button onclick="loginButtonClick()" style="font-size: 20px; color: red;"> 登录 </button>
        <button onclick="logoutButtonClick()" style="font-size: 20px; color: red;"> 登出 </button>
        <button onclick="testJsAlert()" style="font-size: 20px; color: red;"> 测试js弹出框 </button>
        <script src="test2.js"> </script> // 这里有外部链接的js文件,为了结构上的清晰整洁
    </body>
   
</html>

  • 准备一份js文件,内容如下

function loginButtonClick() {
    try {
        webkit.messageHandlers.Login.postMessage("登录");
    } catch(err) {
        console.log('The native context does not exist yet');
    }
}

function logoutButtonClick() {
    try {
        webkit.messageHandlers.Logout.postMessage("登出");
    } catch(err) {
        console.log('The native context does not exist yet');
    }
}

function hello(firstname, lastname) {
     return firstname + lastname;
}

function testJsAlert() {
    alert("捕获js alert事件并弹出窗口");
}

  • 第一个viewcontroller类,点击按钮会跳转到包含webview的view controller

#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

@property (nonatomic, strong) IBOutlet UIButton *loadWebviewButton;

@end


#import "ViewController.h"
#import "WebViewController.h"

@interface ViewController ()

@property (strong, nonatomic)   WKWebView                   *webView;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (IBAction)startLoadingWebView:(id)sender {
    WebViewController *viewController = [[WebViewController alloc] init];
    [self.navigationController pushViewController:viewController animated:YES];
}
@end

////////////////////////////////////////////

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

@interface WebViewController : UIViewController <WKNavigationDelegate, WKUIDelegate, WKScriptMessageHandler>

@end

// 这里因为使用了弹出框,所以需要引用WKUIDelegate,因为需要实现js到objc的通信,所以需要包含WKScriptMessageHandler

#import "WebViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>

@interface WebViewController ()

@property (nonatomic, strong) WKUserContentController *controller;
@property (nonatomic, strong) WKWebView *webView;

@end

@implementation WebViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    //首先定义了configuration,来注册js到objc的通知事件

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
    WKUserContentController *weakController = [[WKUserContentController alloc] init];
    self.controller = weakController;

    [self.controller addScriptMessageHandler:self name:@"Login"];
    [self.controller addScriptMessageHandler:self name:@"Logout"];
    configuration.userContentController = self.controller;
   

   //创建了wkwebview,记得init方法一定要把创建的config传入进去,否则消息无法派发成功。而且这里的方式不是哪self直接malloc的,防止循环引用的出现。

    WKWebView *webViewT = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:configuration];
    self.webView = webViewT;

    NSURL *baseURL = [NSURL fileURLWithPath:[[NSBundle mainBundle] bundlePath]];
    NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"demo"
                                                          ofType:@"html"];
    NSString * htmlCont = [NSString stringWithContentsOfFile:htmlPath
                                                    encoding:NSUTF8StringEncoding
                                                       error:nil];
    [self.webView loadHTMLString:htmlCont baseURL:baseURL];

    self.webView.navigationDelegate = self;
    self.webView.UIDelegate = self;

    [self.view addSubview:self.webView];
    
}

- (void)viewDidDisappear:(BOOL)animated {
    [super viewDidDisappear:animated];

    //记得在使用了add方法添加messagehandler后一定要记得在不用的地方调用remove释放内存资源,否则内存泄露!

    [self.controller removeScriptMessageHandlerForName:@"Login"];
    [self.controller removeScriptMessageHandlerForName:@"Logout"];

}

- (void)dealloc {
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

// 页面开始加载时调用
- (void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"didStartProvisionalNavigation");
}

// 当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"didCommitNavigation");
}

// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"didFinishNavigation");
    //wkwebview objc 调用js 这里只能把单独的js文件以src的形式放到html文件中,然后调用具体的方法即可
    [self.webView evaluateJavaScript:@"hello('lisa', 'liu')" completionHandler:^(id item, NSError * error) {
        NSLog(@"the return message is %@", item);
    }];

}

// 页面加载失败时调用
- (void)webView:(WKWebView *)webView didFailProvisionalNavigation:(WKNavigation *)navigation {
    NSLog(@"didFailProvisionalNavigation");
}

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{
    //js调用native的处理地方。我们可以根据name和body,进行桥协议的处理。
    NSString *messageName = message.name;
    if ([@"Login" isEqualToString:messageName]) {
        [self loginButtonSelectedWithMessageBody:message];
    }
    if (([@"Logout" isEqualToString:messageName])) {
        [self logoutButtonSelectedWithMessageBody:message];
    }

}

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    //wkwebview 默认情况下是禁止js弹出alert框体的,如果想弹出就必须要复写此功能,而且在弹出框体的时候,需要用如下的方式,completionHandler();否则在创建了alertview的同时立即调用completion会造成crash
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:
                                NSLocalizedString(@"Test Alert", nil) message: message
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction* defaultAction = [UIAlertAction actionWithTitle: @"OK"
                                                            style:UIAlertActionStyleDefault handler:^(UIAlertAction * action) {
                                                                completionHandler();
                                                            }];
    [alert addAction:defaultAction];
    [self presentViewController:alert animated:YES completion:nil];
}

- (void)loginButtonSelectedWithMessageBody:(WKScriptMessage *)message {
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:
                                NSLocalizedString(@"Login", nil) message: message.body
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
    [alert addAction:cancelAction];
    [self presentViewController:alert animated:YES completion:nil];
    
    //调用完以后可以再次将想要的输出结果传回给js
    NSString *jsStr = [NSString stringWithFormat:@"hello('%@','%@')",message.name, message.body];
    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {
        NSLog(@"----%@",result);
    }];
}

- (void)logoutButtonSelectedWithMessageBody:(WKScriptMessage *)message {
    UIAlertController* alert = [UIAlertController alertControllerWithTitle:
                                NSLocalizedString(@"Logout", nil) message: message.body
                                                            preferredStyle: UIAlertControllerStyleAlert];
    UIAlertAction *cancelAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleCancel handler:nil];
    [alert addAction:cancelAction];
    [self presentViewController:alert animated:YES completion:nil];
}

@end

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值