这次又是插件开发..需要自定义一个录像机,录完视频后把视频压缩保存本地,并进行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传来的参数
document.addEventListener("event_name", eventFunc, false); function eventFunc(args) { alert(JSON.parse(args.arguments)); };
这样就可以接收到OC传来的参数了