美文网首页
iOS OC与JS互调

iOS OC与JS互调

作者: hongzhenw | 来源:发表于2020-08-24 22:13 被阅读0次

本文介绍的是WKWebView与JS之前的互调

  1. WKWebView的基本设置,如下:
@interface ViewController : UIViewController <WKScriptMessageHandler,WKUIDelegate>

@end

@interface ViewController ()
@property (nonatomic,strong) WKWebView *wkWebView;
@end

- (void)viewDidLoad {
    [super viewDidLoad];
    self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
    // JS的alert、confirm的提示,APP需要处理下
    self.wkWebView.UIDelegate = self;
    // 载入JS页面
    [self.wkWebView loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.5.148:8088/test.html"]]];
    [self.view addSubview:self.wkWebView];
}
  1. JS的alert、confirm在APP上进行提示
# pragma WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    [self showAlert:message isConfirm:NO];
    completionHandler();// 注意completionHandler,必须调,否则会崩
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
    [self showAlert:message isConfirm:YES];
    completionHandler(NO);// 注意completionHandler,必须调,否则会崩
}

- (void)showAlert:(NSString *)str isConfirm:(BOOL)isConfirm{
    NSString *msg = [NSString stringWithFormat:@"\n %@",str];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
    [alert addAction:ok];
    // 是否显示取消按钮
    if (isConfirm) {
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:cancel];
    }
    [self presentViewController:alert animated:YES completion:nil];
}

3.1. APP调用JS方法

// 在APP内viewDidLoad里搞两个APP原生按钮,如下
UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"callJs1" style:UIBarButtonItemStyleDone target:self action:@selector(callJs1)];
UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"callJs2" style:UIBarButtonItemStyleDone target:self action:@selector(callJs2)];
self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:item1,item2, nil];

- (void)callJs1 {
    [self.wkWebView evaluateJavaScript:@"showmsg1('我是来自app的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
        NSLog(@"item=%@,err=%@",item,err);
    }];
}

// JS方法如下
<script>
    function showmsg1(str) {
        alert(str)
    }
</script>

3.2. 另外,APP也可以把自定义的JS方法,注入到JS内,如下

// 把APP自定义的JS方法,注入到JS内
NSString *jsString = @"function appAlert(str) { alert(str);} ";
WKUserScript *script = [[WKUserScript alloc] initWithSource:jsString injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
[ucc addUserScript:script];

// APP调用注入的JS方法
- (void)callJs2 {
    [self.wkWebView evaluateJavaScript:@"appAlert('我是来自app注入方法的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
        NSLog(@"item=%@,err=%@",item,err);
    }];
}

// JS也可以调用APP自定义的JS方法
<script>
    function showmsg2(str) {
        appAlert(str)
    }
</script>
  1. JS调用APP方法
// JS方法如下
<script>
    function call_app_method_1() {
        window.webkit.messageHandlers.app_method_1.postMessage(null)
    }

    function call_app_method_2() {
        window.webkit.messageHandlers.app_method_2.postMessage(['a', 'b', 'c'])
    }
</script>

// 把APP的方法添加到JS内
WKUserContentController *ucc = self.wkWebView.configuration.userContentController;
[ucc addScriptMessageHandler:self name:@"app_method_1"];
[ucc addScriptMessageHandler:self name:@"app_method_2"];

// JS调用APP添加到JS的方法,由下面的方法进行区分
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    NSLog(@"message.name = %@",message.name); // APP方法名
    NSLog(@"message.body = %@",message.body); // JS的入的参数
}
  1. 注意内存回收处理
- (void)dealloc {
    [self.wkWebView.configuration.userContentController removeAllUserScripts];
}

JS完整代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>tit</title>
</head>
<body>
    <input type="button" value="alert1" onclick="showmsg1('我是来自JS的消息1')" />
    <input type="button" value="alert2" onclick="showmsg2('我是来自JS的消息2')" />
    <input type="button" value="alert3" onclick="showmsg3('我是来自JS的消息3')" />
    <input type="button" value="call_app_method_1" onclick="call_app_method_1()" />
    <input type="button" value="call_app_method_2" onclick="call_app_method_2()" />
</body>

<script>

    function showmsg1(str) {
        alert(str)
    }

    function showmsg2(str) {
        appAlert(str)
    }

    function showmsg3(str) {
        confirm(str)
    }

    function call_app_method_1() {
        window.webkit.messageHandlers.app_method_1.postMessage(null)
    }

    function call_app_method_2() {
        window.webkit.messageHandlers.app_method_2.postMessage(['a', 'b', 'c'])
    }

</script>

</html>

APP完整代码:

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

@interface ViewController : UIViewController <WKScriptMessageHandler,WKUIDelegate>
@end

@interface ViewController ()
@property (nonatomic,strong) WKWebView *wkWebView;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // APP原生的两个按钮
    UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"callJs1" style:UIBarButtonItemStyleDone target:self action:@selector(callJs1)];
    UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"callJs2" style:UIBarButtonItemStyleDone target:self action:@selector(callJs2)];
    self.navigationItem.rightBarButtonItems = [NSArray arrayWithObjects:item1,item2, nil];
    
    // WKWebView基本设置
    self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.bounds];
    // JS的alert、confirm的提示,APP需要处理下
    self.wkWebView.UIDelegate = self;
    // 载入JS页面
    [self.wkWebView loadRequest: [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.0.103:8088/test.html"]]];
    [self.view addSubview:self.wkWebView];
    
    // 把APP的方法添加到JS内
    WKUserContentController *ucc = self.wkWebView.configuration.userContentController;
    [ucc addScriptMessageHandler:self name:@"app_method_1"];
    [ucc addScriptMessageHandler:self name:@"app_method_2"];
    // 把APP自定义的JS方法,注入到JS内
    NSString *jsString = @"function appAlert(str) { alert(str);} ";
    WKUserScript *script = [[WKUserScript alloc] initWithSource:jsString injectionTime:WKUserScriptInjectionTimeAtDocumentStart forMainFrameOnly:NO];
    [ucc addUserScript:script];
}

- (void)callJs1 {
    [self.wkWebView evaluateJavaScript:@"showmsg1('我是来自app的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
        NSLog(@"item=%@,err=%@",item,err);
    }];
}

- (void)callJs2 {
    [self.wkWebView evaluateJavaScript:@"appAlert('我是来自app注入方法的消息')" completionHandler:^(id _Nullable item, NSError * _Nullable err) {
        NSLog(@"item=%@,err=%@",item,err);
    }];
}

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

# pragma WKUIDelegate
- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
    [self showAlert:message isConfirm:NO];
    completionHandler();// 注意completionHandler,必须调,否则会崩
}

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
    [self showAlert:message isConfirm:YES];
    completionHandler(NO);// 注意completionHandler,必须调,否则会崩
}

// 注意内存回收处理
- (void)dealloc {
    [self.wkWebView.configuration.userContentController removeAllUserScripts];
}

- (void)showAlert:(NSString *)str isConfirm:(BOOL)isConfirm{
    NSString *msg = [NSString stringWithFormat:@"\n %@",str];
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
    UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:nil];
    [alert addAction:ok];
    // 是否显示取消按钮
    if (isConfirm) {
        UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleDefault handler:nil];
        [alert addAction:cancel];
    }
    [self presentViewController:alert animated:YES completion:nil];
}

@end

相关文章

网友评论

      本文标题:iOS OC与JS互调

      本文链接:https://www.haomeiwen.com/subject/fltojktx.html