js与oc原生WKWebView交互传值

1 篇文章 0 订阅
1 篇文章 0 订阅

最近在做移动端实现H5支付,需要与JS交互,实现状态提醒,参数传值等,在这里总结一下,以防一个月后又忘了〜,

上一篇记录的app微信h5支付唤醒不了微信app,也是算一个bug有需要的可以去看一下

先看下四中交互方式:(我用的第三种,现在都是在用wkwebview不建议用webview)

1.拦截网址(适用于UIWebView和WKWebView) 
2.JavaScriptCore(只适用于UIWebView,iOS7 +) 
3.WKScriptMessageHandler(只适用于WKWebView,iOS8 +) 
4.WebViewJavascriptBridge(适用于UIWebView和WKWebView,属于第三方框架)

 

1,2-不推荐 

方法四WebViewJavascriptBridge

是一个第三方框架,官方文档和demo都很完整,不再累赘,GitHub地址:https: 
//github.com/marcuswestin/WebViewJavascriptBridge

在这里主要记录一下方法三

@interface ViewController()<WKNavigationDelegate,UIScrollViewDelegate,WKUIDelegate,WKScriptMessageHandler>

@property(非原子,强)WKWebView * webView;

@结束

@implementation ViewController

- (void)viewDidLoad {

    [super viewDidLoad];

    WKWebViewConfiguration * config = [[WKWebViewConfiguration alloc] init];

    config.preferences = [[WKPreferences alloc] init];

    config.preferences.minimumFontSize = 10;

    config.preferences.javaScriptEnabled = YES;

    config.preferences.javaScriptCanOpenWindowsAutomatically = NO;

    config.userContentController = [[WKUserContentController alloc] init];

    config.processPool = [[WKProcessPool alloc] init];

    self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds

                                      configuration:config];

    //记得实现对应协议,不然方法不会实现.

    self.webView.UIDelegate = self;

    self.webView.navigationDelegate =self;

    [self.view addSubview:self.webView];

    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://192.168.1.188/index1.html"]]];

  // **************** 此处划重点 **************** //

    //添加注入js方法, oc与js端对应实现

    [config.userContentController addScriptMessageHandler:self name:@"collectSendKey"];

 [config.userContentController addScriptMessageHandler:self name:@"collectIsLogin"];

}

#pragma mark - WKScriptMessageHandler

//实现JS注入方法的协议方法

- (void)userContentController:(WKUserContentController *)userContentController

      didReceiveScriptMessage:(WKScriptMessage *)message {

    //找到对应的js端的方法名,获取messge.body

    if([message.name isEqualToString:@“collectSendKey”]){

 NSLog(@“%@”,message.body);

        }

}

2.浏览网络页面,传递值给JS界面,JS界面通过值判断处理逻辑。

 使用场景:浏览网页面商品,加入购物车,js通过oc原生传递过去的userId是否为空,来判断当前app是否登录,未登录,跳转原生界面登录,已登录,则直接加入购物车

     直接放代码:

#pragma mark --------- WKNavigationDelegate --------------

//加载成功,传递值给js

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation

{

    //获取用户id

//传递userId给js端

   NSString * userId = DEF_GET_OBJECT(UserID);

   NSString * jsUserId;

    if(!userId){

        jsUserId = @“”;

    }其他{

        jsUserId = userId;

    }

    //之所以给userId重新赋值,貌似是如果userId为空null那么传给js端,js说无法判断,只好说,如果userId为null,重新定义为空字符串。如果大家有好的建议,可以在下方留言。   

    //同时,这个地方需要注意的是,JS端并不能查看我们给他传递的是什么值,也无法打印,貌似是语言问题?还是JS骗我文化低,反正,咱们把值传给他,根据双方商量好的逻辑,给出判断,如果正常,那就OK了。

    NSString * jsStr = [NSString stringWithFormat:@“sendKey('%@')”,jsUserId];

    [self.webView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result,NSError * _Nullable error){

  //此处可以打印错误。

    }];

   // JS端获取传递值代码实现实例(此处为JS端实现代码给大家粘出来示范的!!!):

 // function sendKey(user_id){

 $( “#输入”)VAL(USER_ID)。
 }

}

//依然是这个协议方法,获取注入方法名对象,获取JS返回的状态值。

#pragma mark - WKScriptMessageHandler

- (void)userContentController:(WKUserContentController *)userContentController

      didReceiveScriptMessage:(WKScriptMessage *)message {

// js端判断如果userId为空,则返回字符串@“toLogin”,或者返回其它值。JS端代码实现实例(此处为JS端实现代码给大家粘出来示范的!):

function collectIsLogin(goods_id){

                                   if(/(iPhone|iPad|iPod|iOS)/i.test(navigator.userAgent)){


   尝试{


      if($(“#input”)。val()){               
                                            window.webkit.messageHandlers.collectGzhu.postMessage({body:“'”+ goods_id +“'”});

        } else {
                                            window.webkit.messageHandlers.collectGzhu.postMessage({body:'toLogin'});

   }
                                   } catch(e){
                                        //浏览器
                                        alert(e);
                                    }

// OC原生处理:

    if([message.name isEqualToString:@“collectIsLogin”]){

       NSDictionary * messageDict =(NSDictionary *)message.body;

        if([messageDict [@“body”] isEqualToString:@“toLogin”]){

            的NSLog(@ “登录”);          

        }其他{

            的NSLog(@ “正常跳转”);

            NSLog(@“mess --- id ==%@”,message.body);

        }

    }

}

    3.在交互中,关于alert(单对话框)函数,确认(是/否对话框)函数,提示(输入型对话框)函数时,实现代理协议WKUIDelegate,则系统方法里有三个对应的协议方法。大家可以进入WKUIDelegate协议类面面查看。下面具体协议方法实现,也给大家粘出来,以供参考。

#pragma mark - WKUIDelegate

- (void)webViewDidClose:(WKWebView *)webView {

    NSLog(@“%s”,__ FUNCTION__);

}

//在JS端调用alert函数时,会触发此代理方法。

// JS端调用alert时所传的数据可以通过消息拿到

//在原生得到结果后,需要回调JS,是通过completionHandler回调

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

    NSLog(@“%s”,__ FUNCTION__);

    UIAlertController * alert = [UIAlertController alertControllerWithTitle:@“alert”消息:@“JS调用警报”preferredStyle:UIAlertControllerStyleAlert];

    [alert addAction:[UIAlertAction actionWithTitle:@“确定”样式:UIAlertActionStyleDefault处理程序:^(UIAlertAction * _Nnnull action){

        completionHandler();

    }]]; 

    [self presentViewController:alert animated:YES completion:NULL];

    NSLog(@“%@”,消息);

}

// JS端调用确认函数时,会触发此方法

//通过消息可以拿到JS端所传的数据

//在iOS端显示原生警告得到是/否后

//通过completionHandler回调给JS端

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

    NSLog(@“%s”,__ FUNCTION__);

    UIAlertController * alert = [UIAlertController alertControllerWithTitle:@“confirm”消息:@“JS调用确认”preferredStyle:UIAlertControllerStyleAlert];

    [alert addAction:[UIAlertAction actionWithTitle:@“确定”样式:UIAlertActionStyleDefault处理程序:^(UIAlertAction * _Nnnull action){

        completionHandler(YES);

    }]];

    [alert addAction:[UIAlertAction actionWithTitle:@“取消”样式:UIAlertActionStyleCancel处理程序:^(UIAlertAction * _Nnnull action){

        completionHandler(NO);

    }]];

    [self presentViewController:alert animated:YES completion:NULL];

    NSLog(@“%@”,消息);

}

// JS端调用提示函数时,会触发此方法

//要求输入一段文本

//在原生输入得到文本内容后,通过completionHandler回调给JS

- (void)webView:(WKWebView *)webView runJavaScriptTextInputPanelWithPrompt:(NSString *)prompt defaultText :( nullable NSString *)defaultText initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void(^)(NSString * __nullable result))completionHandler {

    NSLog(@“%s”,__ FUNCTION__);

    NSLog(@“%@”,提示);

    UIAlertController * alert = [UIAlertController alertControllerWithTitle:@“textinput”message:@“JS调用输入框”preferredStyle:UIAlertControllerStyleAlert];

    [alert addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField){

        textField.textColor = [UIColor redColor];

    }]; 

    [alert addAction:[UIAlertAction actionWithTitle:@“确定”样式:UIAlertActionStyleDefault处理程序:^(UIAlertAction * _Nnnull action){

        completionHandler([[alert.textFields lastObject] text]);

    }]];

    [self presentViewController:alert animated:YES completion:NULL];

}

文章参考https://blog.csdn.net/dolacmeng/article/details/79623708

这篇文章也不错https://blog.csdn.net/hanhailong18/article/details/69102820

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值