我爱编程面试ios视频缓存

OC与JS交互

2018-05-23  本文已影响49人  寻形觅影

关于UIWebView与JS的交互:

 这里先声明一下:示例只放上了重点代码,后面会给demo地址。

1、原始交互方法:

1、OC调用JS:向UIWebView发送- (nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;消息来执行一段JavaScript脚本;这里需要注意的是:该方法必须在主线程调用,否则不起作用。

2、JS调用OC:在UIWebView的代理方法- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;中拦截URL然后重定向去执行OC相关代码;

示例:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    // 原始的JS调用OC,拦截URL,重定向
    // 这里我在 index.html中采用了两种方式进行request返回,1:onclick="window.open('need://transform')";2:onclick="window.location.href='need://location'"
    if ([request.URL.absoluteString hasPrefix:@"need://transform"]) {// 跳转
        NSLog(@"执行了跳转操作");
        return NO;
    }
    if ([request.URL.absoluteString hasPrefix:@"need://location"]) {// 本界面的一些操作
        NSLog(@"执行了本界面操作");
        return NO;
    }
    return YES;
}

// 这里是点击了OC中一个原生的button所执行的方法
- (void)rightButAction:(UIButton *)sender
{
        // 使用UIWebView自带方法调用JS方法,其中picCallback('%@')是JS方法,后面是参数
        NSString * jsStr = [NSString stringWithFormat:@"picCallback('%@')", @"stringByEvaluatingJavaScriptFromString方法实现"];
        [self.mainWebView stringByEvaluatingJavaScriptFromString:jsStr];
}
2、使用JavaScriptCore:

  关于JavaScriptCore框架可以参考这篇文章,当使用时需要先导入该框架头文件#import <JavaScriptCore/JavaScriptCore.h>
1、OC调用JS: 在代理方法- (void)webViewDidFinishLoad:(UIWebView *)webView中获取交互上下文对象(JSContext) ,然后调用JSContext- (JSValue *)evaluateScript:(NSString *)script;方法执行JS代码;

2、JS调用OC:这里有两种方法,一种是针对JS中未指明调用对象的方法,一种是针对JS中指明调用对象的方法。

示例:

// JS调用OC
@protocol JSObjcDelegate <JSExport>
//协议的方法必须和JS里面的方法名称保持一致才有效!
- (void)callShare;
@end

@interface JRWebViewMutualViewController ()<UIWebViewDelegate, JSObjcDelegate>
@property (nonatomic,strong) JSContext * jsContext;// 获取交互环境,主要用于调取JS代码
@property(strong,nonatomic)UIWebView * mainWebView;
@end

@implementation JRWebViewMutualViewController

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.jsContext = [self.mainWebView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
    // 未指明调用对象的方法
    self.jsContext[@"callCamera"] = ^() {
        NSLog(@"调用Camera了🙄");
    };
    /**
        在JS中 onclick="callCamera()" 指的是点击button直接触发callCamera方法;
        onclick="TEXT.callShare() 指点击button会让一个叫做TEXT的对象去触发callShare方法;
     */
    //在使用JSExport协议类时必须有指定的执行对象才能使用否则使用block形式的回调即可
    self.jsContext[@"TEXT"] = self;
    // 若发生异常会执行此方法
    self.jsContext.exceptionHandler = ^(JSContext *context, JSValue *exception) {
        NSLog(@"异常信息是%@",exception);
    };
}

- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error
{
    NSLog(@"加载错误:%@", error);
}

// 这里是点击了OC中一个原生的button所执行的方法
- (void)rightButAction:(UIButton *)sender
{
        // 获取 将字符串对应的JS方法,转换成一个JSValue对象
        JSValue * jsValue = [self.jsContext evaluateScript:@"picCallback"];
        // 下面👇这一方法与上面的等效
//        JSValue * jsValue = self.jsContext[@"picCallback"];
        // 作为一个函数调用JSValue 参数是JS函数所需参数,该方法用于传参
        [jsValue callWithArguments:@[@"javaScript实现"]];
        
        // 与上面两句代码等效代码
//        [self.jsContext evaluateScript:[NSString stringWithFormat:@"picCallback('%@')", @"javaScript实现"]];
}

- (void)callShare
{
    NSLog(@"调用Share了🙄");
}
@end

 在这里因为若没有HTML的代码可能会不是那么清晰,附上HTML的代码,里面比较简单:

<!DOCTYPE html>  
<html>  
<head lang="zh-CN">
    <meta charset="UTF-8">
    <title>OC-JS交互</title>
</head>  
<body>  
    <div style="margin-top: 30px">
        <input type="button" value="调用OC原生代码示例 - 拦截协议,跳转界面" onclick="window.open('need://transform')" style = "width:300px;height:30px;border:0px;background-color:red;margin-left:10px" >
    </div>         
  
    <div>  
        <input type="button" value="调用OC原生代码示例 - 拦截协议,本界面做操作" onclick="window.location.href='need://location'" style = "width:300px;height:30px;border-style:none; background-color:#FF9;margin-left:10px; margin-top:10px">
    </div>
    
    <div>
        <p>&lt;1&gt;和后端同事协定好协议,如need://transform表示跳转,need://location表示本界面的其他操作。 <br>
        &lt;2&gt;实现UIWebView代理的shouldStartLoadWithRequest:navigationType:方法,在方法中对url进行拦截,如果是步骤 &lt;1&gt; 中定义好的协议则执行对应原生代码,返回NO进行url拦截,否则返回YES继续加载原url。</p>
    <div>
        
    <div style="margin-top: 10px">
        <input type="button" value="调用OC原生代码示例 - JSCore,跳转界面" onclick="callCamera()" style = "width:300px;height:30px;border:0px;background-color:red;margin-left:10px" >
            </div>
    
    <div>
        <input type="button" value="调用OC原生代码示例 - JSCore,本界面做操作" onclick="TEXT.callShare()" style = "width:300px;height:30px;border-style:none; background-color:#FF9;margin-left:10px; margin-top:10px">
            </div>
  
<script>  

    var picCallback = function(photos) {  
        alert(photos);  
    }  

</script>

</body>  
</html>  

demo 地址,demo是一个项目集合,暂时没什么东西,会后续往里面加入,交互界面在左侧抽屉中😆。

上一篇 下一篇

猜你喜欢

热点阅读