美文网首页
iOS JS和原生交互(整理)

iOS JS和原生交互(整理)

作者: smile_frank | 来源:发表于2021-03-12 10:31 被阅读0次

WKWebView交互

1.JS调OC

方案1:主要是通过拦截URL,做协议字符匹配(如:js_native://alert

//需要先遵循WKNavigationDelegate协议
//在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    NSURL *url = navigationAction.request.URL;
    if ([[url absoluteString] hasSuffix:@"js_native://alert"]) {
        [self handleJSMessage];
        //不允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
        return;
    }
    //允许跳转
    decisionHandler(WKNavigationActionPolicyAllow);
    
}

js部分代码

function  jsCallNativeMethod(){
    location.href = "js_native://alert";
}

方案2:WKScriptMessageHandler js方法名匹配 (如:bf_jsCallNativeMethod)

- (WKWebView *)webView {
    if (!_webView) {
        //网页配置文件
        WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc]init];
        //允许与网页交互
        configuration.selectionGranularity = YES;
        configuration.userContentController = [WKUserContentController new];
        WKPreferences *preferences = [WKPreferences new];
        preferences.javaScriptCanOpenWindowsAutomatically = YES;
        preferences.minimumFontSize = 50;
        configuration.preferences = preferences;
        
        configuration.userContentController = [WKUserContentController new];
        [configuration.userContentController addScriptMessageHandler:self name:@"bf_jsCallNativeMethod"];
        
        _webView = [[WKWebView alloc]initWithFrame:self.view.bounds configuration:configuration];
        _webView.navigationDelegate = self;
        _webView.UIDelegate = self;
    }
    return _webView;
}

//遵循WKScriptMessageHandler协议
- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message {
    
    if ([message.name isEqualToString:@"bf_jsCallNativeMethod"]) {
        NSLog(@"这个是传过来的参数%@",message.body);
    }
}

/*要记得销毁是移除*/
- (void)dealloc
{
    [self.webView.configuration.userContentController removeScriptMessageHandlerForName:@"bf_jsCallNativeMethod"];
}

js部分代码

function bf_jsCallNativeMethod() {
    window.webkit.messageHandlers.bf_jsCallNativeMethod.postMessage('我的参数222');
}

方案3 主要是js中弹窗监听 比如: 警告框, 选择框, 输入框等监听

#pragma mark- WKUIDelegate

// WKUIDelegate是web界面中有弹出警告框时调用这个代理方法,主要是用来处理使用系统的弹框来替换JS中的一些弹框的,比如: 警告框, 选择框, 输入框等
/**
 webView中弹出警告框时调用, 只能有一个按钮
 @param webView webView
 @param message 提示信息
 @param frame 可用于区分哪个窗口调用的
 @param completionHandler 警告框消失的时候调用, 回调给JS
 */

- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler {
  
    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"温馨提示" message:message preferredStyle:UIAlertControllerStyleAlert];
    [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:nil]];
    [self presentViewController:alert animated:YES completion:nil];
    completionHandler();
    
}

// JavaScript调用confirm方法后回调的方法 confirm是js中的确定框,需要在block中把用户选择的情况传递进去

/** 对应js的confirm方法
 webView中弹出选择框时调用, 两个按钮
 @param webView webView description
 @param message 提示信息
 @param frame 可用于区分哪个窗口调用的
 @param completionHandler 确认框消失的时候调用, 回调给JS, 参数为选择结果: YES or NO
 */

- (void)webView:(WKWebView *)webView runJavaScriptConfirmPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(BOOL))completionHandler {
  
}

// JavaScript调用prompt方法后回调的方法 prompt是js中的输入框 需要在block中把用户输入的信息传入

/** 对应js的prompt方法
 webView中弹出输入框时调用, 两个按钮 和 一个输入框
 
 @param webView webView description
 @param prompt 提示信息
 @param defaultText 默认提示文本
 @param frame 可用于区分哪个窗口调用的
 @param completionHandler 输入框消失的时候调用, 回调给JS, 参数为输入的内容
 */

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText:(NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(NSString * _Nullable))completionHandler {
   
       UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"请输入" message:prompt preferredStyle:(UIAlertControllerStyleAlert)];
       [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
       textField.placeholder = @"请输入";
       }];
       UIAlertAction *ok = [UIAlertAction actionWithTitle:@"确定" style:(UIAlertActionStyleDefault) handler:^(UIAlertAction * _Nonnull action) {
       UITextField *tf = [alert.textFields firstObject];
       completionHandler(tf.text);
           
       }];
       UIAlertAction *cancel = [UIAlertAction actionWithTitle:@"取消" style:(UIAlertActionStyleCancel) handler:^(UIAlertAction * _Nonnull action) {
       completionHandler(defaultText);
       }];
       [alert addAction:ok];
       [alert addAction:cancel];
       [self presentViewController:alert animated:YES completion:nil];

}

2.OC调JS
调用苹果提供的API

- (void)evaluateJavaScript:(NSString *)javaScriptString completionHandler:(void (^ _Nullable)(_Nullable id, NSError * _Nullable error))completionHandler;

使用方式

 [_webView evaluateJavaScript:@"nativeCallbackJscMothod('123')" completionHandler:^(id _Nullable x, NSError * _Nullable error) {
        NSLog(@"x = %@, error = %@", x, error.localizedDescription);
    }];

JS部分

function nativeCallbackJscMothod(arguments) {
    alert('原生调用js方法 传来的参数 = ' + arguments);
}

其他

#pragma mark- WKNavigationDelegate
/*
 WKNavigationDelegate主要处理一些跳转、加载处理操作
 
 */

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

//当内容开始返回时调用
- (void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation {
    NSLog(@"----页面返回内容");
}
//页面加载完成时调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation {
    NSLog(@"----页面加载完成");
//    //原生回调JS
//    [self.webView evaluateJavaScript:@"nativeCallbackJscMothod('我是回调')" completionHandler:^(id _Nullable s, NSError * _Nullable error) {
//        NSLog(@"执行完成啦");
//    }];
    
}

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

//接收到服务器跳转请求之后调用
- (void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation {
    
    NSLog(@"----接收到服务器跳转请求之后调用");
}

//在收到响应后,决定是否跳转
-(void)webView:(WKWebView *)webView decidePolicyForNavigationResponse:(WKNavigationResponse *)navigationResponse decisionHandler:(void (^)(WKNavigationResponsePolicy))decisionHandler {
  
    NSLog(@"%@",navigationResponse.response.URL.absoluteString);
    //允许跳转
    decisionHandler(WKNavigationResponsePolicyAllow);
    //不允许跳转
    //decisionHandler(WKNavigationResponsePolicyCancel);
}

//在发送请求之前,决定是否跳转
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler {
    
    NSURL *url = navigationAction.request.URL;
    if ([[url absoluteString] hasSuffix:@"js_native://alert"]) {
        [self handleJSMessage];
        //不允许跳转
        decisionHandler(WKNavigationActionPolicyAllow);
        return;
    }
    //允许跳转
    decisionHandler(WKNavigationActionPolicyAllow);
    
}

/* 需要响应身份验证时调用,同样在block中需要传入用户身份凭证 */
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler {
    //用户身份信息
       NSLog(@"----需要响应身份验证时调用 同样在block中需要传入用户身份凭证");
       NSURLCredential *newCard = [NSURLCredential credentialWithUser:@"" password:@"" persistence:NSURLCredentialPersistenceNone];
       // 为 challenge 的发送方提供 credential
       [[challenge sender] useCredential:newCard forAuthenticationChallenge:challenge];
       completionHandler(NSURLSessionAuthChallengeUseCredential,newCard);
}

/* 进程被终止时调用 */
- (void)webViewWebContentProcessDidTerminate:(WKWebView *)webView {
    NSLog(@"----进程被终止时调用");
}

/* 关闭webView时调用的方法 */
- (void)webViewDidClose:(WKWebView *)webView {
    NSLog(@"----关闭webView时调用的方法");
}

后续继续整理更多方案

相关文章

网友评论

      本文标题:iOS JS和原生交互(整理)

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