揭开OC与JS交互调用的神秘面纱

首先OC里要和JS去交互,先行引入头文件#import
同样的,创建一个和屏幕大小的webView用于渲染HTML的页面,

    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    NSString * htmlPath = [[NSBundle mainBundle] pathForResource:@"index"
                                                          ofType:@"html"];
    NSString * htmlCont = [NSString stringWithContentsOfFile:htmlPath
                                                    encoding:NSUTF8StringEncoding
                                                       error:nil];
    self.webView.delegate = self;
    [self.webView loadHTMLString: htmlCont baseURL:baseURL];

接下来写了一段蹩脚的HTML代码如下:
index.html



   
       
           OC与JS交互
           
           
           
           
           
           
   
   
   
       
       


















![](test.jpg)
小方块
将以上代码放到浏览器中渲染,只能看到几个按钮,一个破图片,点击的话也只有第一个弹框有反应,其他的都反应,因为内在逻辑实现的是按钮点击是有OC代码来反馈以及调用,比如弹起键盘,弹起原生的弹窗,收起键盘...打开系统相机相册等操作.

1. OC里调用JS的函数

一般这种情况是直接监听JS定义的函数

#pragma mark- 戳按钮,OC监听获取JS传过来的参数 [JS调用OC]
- (void)js_ocCallBack{
    JSContext *js = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    js[@"wgb_iOSHookJSButtonClick"] = ^(){
        NSArray *args = [JSContext currentArguments];
        NSString *arg = [args.firstObject toString];
        NSLog(@"arg = %@",arg);
        dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"JS调用OC,JS传过来的参数是" message: arg delegate:self cancelButtonTitle:@"确认" otherButtonTitles:nil];
            [alertView show];
        });
    };
}

//JS里的代码是这样的:
function secondClick(index) {
                    wgb_iOSHookJSButtonClick(index);
                }
///三个`button` `onclick`调用 `secondClick(1)` ,`secondClick(2)` `secondClick(3)`这样子,然后JS走index,  OC 调用`wgb_iOSHookJSButtonClick `,获取到参数值就是JS传过去的index,每次点击只传一个值.

2. JS里调用OC的函数

比如说JS调用原生的键盘啊,相机相册啥的...

#pragma mark- 弹起键盘
- (void)alertKeyboard{
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"jsCallOCAlertKeyboard"] = ^(){ 
///这个方法名和前端的同学约定好就ok的
    dispatch_async(dispatch_get_main_queue(), ^{
        UITextField *textfiled = [[UITextField alloc] initWithFrame:CGRectMake(0, 0, 100, 10)];
        [self.view addSubview: textfiled];
        textfiled.hidden = YES;
        [textfiled becomeFirstResponder];
      });
    };
}

#pragma mark- 退出原生键盘
- (void)wgb_keyboardResignFirstResponder{
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"wgb_keyboardResignFirstResponder"] = ^(){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.view endEditing:YES];
        });
    };
}

#pragma mark- 指定一个方法去调用 相机/相册 选择图片
- (void)js_callOCPhotoPickerImage{
    JSContext *context = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    context[@"iOSImageUpLoad"] = ^(){
        dispatch_async(dispatch_get_main_queue(), ^{
            [self.manager quickAlertSheetPickerImage];
        });
    };
}

以上这几个函数在网页加载完毕的时候就可以直接调用的
// 加载完成开始监听js的方法
- (void)webViewDidFinishLoad:(UIWebView *)webView{
   JSContext *jsContext = [self.webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    jsContext[@"iosDelegate"] = self;
    jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception){
        context.exception = exception;
        NSLog(@"获取 self.jsContext 异常信息:%@",exception);
    };
}


- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
    [self js_ocCallBack];
    [self oc_jsCallBack];
    [self alertKeyboard];
    [self wgb_keyboardResignFirstResponder];
    [self js_callOCPhotoPickerImage]; 
    return YES;
}

Github Demo地址

你可能感兴趣的:(揭开OC与JS交互调用的神秘面纱)