HBuilder OC向JS传参

这次又是插件开发..需要自定义一个录像机,录完视频后把视频压缩保存本地,并进行base64编码传给JS。

JS调用OC


HBuilder给的文档有详细说明怎么配置插件,我之前的一篇文章也有介绍,这就不在一一赘述了,接下来要说的是开发过程中遇到的一些问题和最终的解决方案,希望对有需要的人有所帮助,也是给自己的一种记录。

首先说下JS端打开iOS原生的viewController,以前一直认为不能代开原生页面,感觉像是打开另一个App一样..最后发现其实他也属于混合开发,下面是弹出视图的方法,把此方法写入插件方法内

CameraVC* camera = [[CameraVC alloc] init];
//这里一定要用 self.rootViewController,使其变为跟视图,并且要用模态弹出的方式来弹出视图        
[self.rootViewController presentViewController:camera animated:YES completion:nil];

这样就实现了通过JS来打开iOS原生页面

OC调用JS


开发中遇到的另一个问题就是OC向JS传值的问题了,官网只给出了 JavaScript 调用 native 代码的接口,对于 native 调用 JavaScript 并且向 JavaScript 发送 event 事件的方法却在 native层 进行了封装

OC向JS传值的方法大体上都是

stringByEvaluatingJavaScriptFromString

这个方法,那就开始找吧..

最后发现,在inc中的PDRCoreAppFrame.h中,有这个方法:

/**
 @brief 在当前页面同步执行Javascript
 @param js javasrcipt 脚本
 @return NSString* 执行结果
 */
- (NSString*)stringByEvaluatingJavaScriptFromString:(NSString*)js;
获取PDRCoreAppFrame对象

其中 PDRCoreAppFrame 为控制 webView 的实例,数量可能为多个,且在视图层级中的位置不确定,故需要通过遍历 app 中所有 view ,来找到PDRCoreAppFrame:

- (NSMutableArray*)searchViews:(NSArray*)views{

    NSMutableArray *frames = [NSMutableArray array];
    //遍历view
    for (UIView *temp in views) {
        
        if ([temp isMemberOfClass:[PDRCoreAppFrame class]]) {
            
            [frames addObject:temp];
        }
        if ([temp subviews]) {
            
            NSMutableArray *tempArray = [self searchViews:[temp subviews]];
            
            for (UIView *tempView in tempArray) {
                
                if ([tempView isMemberOfClass:[PDRCoreAppFrame class]]) {
                    
                    [frames addObject:tempView];
                }
            }
        }
    }
    //返回值 frames 为从该层级中找到的 PDRCoreAppFrame
    return frames;
}
调用JS

-(void)evaluatingJavaScriptFromString:(NSString*)string{

    UIWindow *window = [[UIApplication sharedApplication] keyWindow];

    NSArray *views = [[[window rootViewController] view] subviews];
    
    NSArray *frames = [self searchViews:views];
    
    NSLog(@"views == %@",frames);
    
    for (PDRCoreAppFrame *appFrame in frames) {
        /*这里需要注意执行异步任务,在block内需要回到主线程来进行JS event的调用,但是如果还是使用
          dispath_get_main_queue的话会造成调用JS有alert的话线程会死锁,具体原因也不是特别清晰,
          在stackOverFlow中看到应该是JS和OC不同alert线程的原因
        */
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
            
            [appFrame performSelectorOnMainThread:@selector(stringByEvaluatingJavaScriptFromString:) withObject:string waitUntilDone:NO];
            
        });
    }
}
向JS发送event
(void)fireEvent:(NSString*)event args:(NSString *)args{
    NSString *evalStr = nil;
    
    if (args) {
        //创建js事件
        evalStr = [NSString stringWithFormat:@"\
                      var pathEvent = document.createEvent('HTMLEvents');\
                      pathEvent.initEvent('%@', true, true);\
                      pathEvent.eventType = 'message';\
                      pathEvent.arguments = '%@';\
                      document.dispatchEvent(pathEvent);",event,args];
    }else{
        evalStr = [NSString stringWithFormat:@"\
                      var pathEvent = document.createEvent('HTMLEvents');\
                      pathEvent.initEvent('%@', true, true);\
                      pathEvent.eventType = 'message';\
                      document.dispatchEvent(pathEvent);",event];
    }
    //调用上述方法
    [self evaluatingJavaScriptFromString:evalStr];
}

最后通过调用

[self fireEvent:@"event_name" args:args];

向JS发送event

js接收event并处理

接收上一步发送的"event_name"事件,js进行捕获

//接收OC传来的参数
document.addEventListener("event_name", eventFunc, false); 
    function eventFunc(args) {
        alert(JSON.parse(args.arguments));
    };

这样就可以接收到OC传来的参数了


posted @ 2017-12-29 14:09  李世林11  阅读(155)  评论(0编辑  收藏  举报