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传来的参数了