IOS和JS交互那点事

很早之前有个项目牵扯到这块就很想写篇博客记录下这篇文章了,这阵子有个项目又刚好遇到,正好有空,记录记录。

跟web的同鞋打过交道的肯定都知道,只要是涉及双端交互就两种方案啦。

  • 截取链接,一般也就通过UIWebView回调代理shouldStartLoadWithRequest截取固定链接然后在原生里面做相应的业务操作,实现也比较简单,当然这个方案也是一般涉及业务简单时候可以用,比如给个固定链接跳转原生界面,如果业务复杂点web要给原生传递参数或者多个参数再或者原生要操作web里面的相关业务,那就得考虑下面的方案二了。

  • JS交互,iOS7以前我们对JS的操作只有webview里面一个函数 stringByEvaluatingJavaScriptFromString,当然也有很多人是用的这个第三方JavascriptBridge,IOS7之后,苹果可能也考虑到了这方面的需求,也很给力推出了JavaScriptCore这个框架。

通过stringByEvaluatingJavaScriptFromString 实现OC执行JS代码

stringByEvaluatingJavaScriptFromString 这个方法是UIWebView里面的方法,也是最为简单的和JS交互的方式。

-(nullable NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script;

用法比较简单,一般在代理方法- (void)webViewDidFinishLoad:(UIWebView*)webView中使用。

- (void)webViewDidFinishLoad:(UIWebView*)webView
{
    // 获取当前页面的title
    NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
    // 获取当前页面的url
    NSString *url = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
}

JavaScriptCore

这是IOS7后苹果推出了JavaScriptCore这个框架,让原生和web界面交互非常方便了。代码是开源的JavaScriptCore 可以下载下来看看。

我们先了解下里面常见的属性和协议

  • JSContext:给JavaScript提供运行的上下文环境,通过-evaluateScript:方法就可以执行一JS代码。
  • JSValue:JavaScript和Objective-C数据和方法的桥梁,封装了JS与ObjC中的对应的类型,以及调用JS的API等。
  • JSManagedValue:管理数据和方法的类JSVirtualMachine:处理线程相关,使用较少。
  • JSExport:这是一个协议,如果JS对象想直接调用OC对象里面的方法和属性,那么这个OC对象只要实现这个JSExport协议就可以了。

OC调JS


    self.context = [[JSContext alloc] init];

    [self.context evaluateScript:@"function reduce(a,b) {return a-b}"];

    JSValue *value = [self.context[@"reduce"] callWithArguments:@[@10, @3]];

    NSLog(@"---%@", @([value toInt32]));    //---7

JS调OC

JS调用OC有两个方法:block和JSExport protocol。

html实现代码

<input type="button" value="JS调用原生block实现" onclick="alert('alert');" />
<input type="button" value="JS调用原生JSExport protocol实现" onclick="native.alert('alert');" />

oc实现代码

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    self.context = [webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    // 打印JS异常
    self.context.exceptionHandler =
    ^(JSContext *context, JSValue *exceptionValue)
    {
        context.exception = exceptionValue;
        NSLog(@"%@", exceptionValue);
    };

    // 以 block 形式关联 JavaScript function
    self.context[@"alert"] =
    ^(NSString *alertText)
    {
        UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertText message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
        [alert show];
    };
    
    // 以 JSExport 协议关联 native 的方法
    self.context[@"native"] = self;
}

当前类需要声明和实现JSExport协议

@protocol TestJSExport <JSExport>
-(void)alert:(NSString *)alertText;
@end

@interface JSCallOCViewController : UIViewController<TestJSExport>
@property (strong, nonatomic) JSContext *context;
@end

#pragma mark - JSExport Methods
-(void)alert:(NSString *)alertText
{
    UIAlertView *alert = [[UIAlertView alloc]initWithTitle:alertText message:nil delegate:nil cancelButtonTitle:@"ok" otherButtonTitles:nil, nil];
    [alert show];
}

好啦,关于JavaScriptCore的基本介绍就是这样了。
参考http://www.jianshu.com/p/a329cd4a67ee

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 跟原生开发相比,H5的开发相对来一个成熟的框架和团队来讲在开发速度和开发效率上有着比原生很大的优势,至少不用等待审...
    大冲哥阅读 1,859评论 0 7
  • 随着H5技术的兴起,在iOS开发过程中,难免会遇到原生应用需要和H5页面交互的问题。其中会涉及方法调用及参数传值等...
    Chris_js阅读 3,109评论 1 8
  • 昨晚因走错了路差点没赶上最后一班地铁。空旷的马路除了偶尔飞驰而过的货车就是路边草丛中的虫鸣声。 昏黄的灯光下是我快...
    红莺萝阅读 574评论 4 6
  • 文/无可救药的文艺青年 BGM:Say you won't let go 我来到你的生命里,陪你度过黑夜,天亮后我...
    无可救药的文艺青年阅读 495评论 0 6
  • 大地在慢慢的恢复着生机 幸存者并不被地震所征服 看,倒塌的房子重新矗立起来 听,教室里又响起了浪浪读书声 美好的生...
    情话总是那么美阅读 504评论 0 1