来了,iOS的JSCore与H5的交互

2019-12-18 10:50:38 浏览数 (1)

h5概念很热,咱们不多多说,但是在移动端的App中某些需要快速开发的地方也是很有好处--可以把一部分不想做的,不方便做的甩给web端去做,咱么只需要做好native与web的通信就好啦?

今天的主角就是JSCore这个哥们,苹果爸爸开放出来很久被大家忽略的角色。这是一个很方便的进行JS与WebView进行通信的神器。既然是神器就理所当然能够方便的进行两端的相互通信。

在开始之前我们先来一个简单相互通信实例(大图)

1 native主动与WebView通信

2 webview调用native

在说通信之前我们先需要搞明白一个东西:WebView调用Native,native调用WebView肯定是相互知道对方的存在保存了对方的instance才行。我们先看一官方的文档

那么这个context我们怎么获取到呢?

代码语言:javascript复制
[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

通过kvo我们可以从WebView中获取到,这个就是我们主动与js打招呼的桥梁。那么有了桥梁我们同样需要给WebView说一声让他知道native的存在---

self.ctx[@"App"] = self;

这样相互直接就知道对方的存,js通过App这个作为native的引用,native通过context进行发消息

1 native 主动发消息给WebView

上文我们拿到了js上下文,就可以直接调用js的function啦,例如我们传递网络中的token

代码语言:javascript复制
    [self.ctx[@"getToken"] callWithArguments:@[[AppManager manager].token]];

2 js主动发送数据给native

这个过程稍微复杂点,需要通过Protocol来实现,可以拆分为两步:

① 声明通信接口

@protocol App <JSExport>

JSExportAs(popBack, -(void)popBack:(NSString *) action );

JSExportAs(look, -(void)lookGameDetail:(NSString *)spotid type:(NSInteger) type );

JSExportAs(refreshToken, -(void)refreshToken:(NSString *) action );

JSExportAs(pushToFishSpot, -(void)pushToFishSpot:(NSInteger) spotId );

@end

这里的JSExportAs是给我们的函数起了一个js调用的function起了个别名,进而兼容转换一线js的function与OC的函数的差异。

但是有一个点需要注意,我们暴露出的共js调用至少需要一个形参,也就是说,不传递数据也要有一个参数

② 传递给WebView的引用实现协议与函数

这里我们只看一个实现

-(void)popBack:(NSString *)action{

@weakify(self)

dispatch_async(dispatch_get_main_queue(), ^{

[weak_self.navigationController popViewControllerAnimated:YES];

});

}

这里有点需要注意:回来进行UI的操作请在主线程中操作

最后是一个兼容性的彩蛋,也是最坑的一点---alert

UIAlert在iOS 9之后慢慢被禁用,而到了iOS13之后这问题异常严重,然鹅直接js进行alert居然报错,好在是哟办法的

这里附上几种带和不带输入和提示框的webview的alert的处理方法

代码语言:javascript复制
 self.ctx[@"window"][@"alert"] = ^(JSValue *message) {
                dispatch_async(dispatch_get_main_queue(), ^{
                //自定义原生提示框替换原来的提示框
        //           message.isString message.isBoolean
        //            [message toString]
        //            [message toBool]
                    
                     UIAlertController * alerVc = [UIAlertController alertControllerWithTitle:@"alert"
                                                                                     message: [message toString] preferredStyle:UIAlertControllerStyleActionSheet];
                    UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"OK" style:0
                                                                          handler:^(UIAlertAction * _Nonnull action) {
                        
                    }];
                    [alerVc addAction:cancelAction];
                    
                    [self presentViewController:alerVc
                                       animated:YES
                                     completion:^{
                        
                    }];
                });
            };
            //解决confirm提示框显示异常问题
            self.ctx[@"window"][@"confirm"]=^(JSValue *message) {
                dispatch_async(dispatch_get_main_queue(), ^{
                  //自定义原生提示框替换原来的提示框
                    
                    
                               UIAlertController * alerVc = [UIAlertController alertControllerWithTitle:@"alert"
                                                                                                message: [message toString] preferredStyle:UIAlertControllerStyleActionSheet];
                               UIAlertAction * cancelAction = [UIAlertAction actionWithTitle:@"OK" style:0
                                                                                     handler:^(UIAlertAction * _Nonnull action) {
                                   
                               }];
                               [alerVc addAction:cancelAction];
                               
                               [self presentViewController:alerVc
                                                  animated:YES
                                                completion:^{
                                   
                               }];
                    
                });
            };
            //解决prompt提示框显示异常问题
            self.ctx[@"window"][@"prompt"] = ^(JSValue *message) {
                dispatch_async(dispatch_get_main_queue(), ^{
                  //自定义原生提示框替换原来的提示框
                    
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"alert" message:[message toString] delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
                    [alert show];
                });
            };
 

0 人点赞