JS和OC的交互(基于UIWebView)

作者: ccc小yyy | 来源:发表于2016-04-27 11:12 被阅读5453次

    前言

    最近要把网页端的商城接入app,其中就要用到JS和OC的交互,我自己也根据在Google上查到的资料试了几种方式,下面稍微总结一下。


    过程

    JS和OC的交互分为两种方式:JS调用OC以及OC调用JS,一般的原则是如果JS想传值给OC就用JS调用OC,相反则用OC调用JS

    传统的方式:

    OC调用JS:

    webView对象通过调用stringByEvaluatingJavaScriptFromString这个方法执行一段JS代码实现交互。如:

    self.title = [self.webView stringByEvaluatingJavaScriptFromString:@"document.title"];

    便可获得标题,这里比较简单,就此略过......

    JS调用OC:webView拦截链接的方法

    -(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType;

    实现以上webView的代理方法,当webView每次开始加载URL时会进入这个方法,我们便可以在这个方法实现JS调用OC。

    JS代码如下:

    OC代码如下:

    如上图当JS中window.location.href = "iOS:shareToTest"的代码被触发,会进入OC中的这个代理方法,并且获得"iOS:shareToTest"这个字符串,接下进行一系列的字符串解释,得到需要被实现的方法名且调用。如果需要传值可把需要传的值拼接在字符串上,字符串解释后获取响应的值后调用一下方法:

    这种JS调用OC的方法的缺点十分明显,需要繁琐地解释字符串得到相应的方法名和传值,且最多只能有两个值,调用的方法也不能传递返回值;但是也有一个优点:不需要等待页面加载完才触发当相应的代码被运行就能调用OC的方法,这也是下面要讲到的JavaScriptCore的一个小坑。

    苹果推荐的框架--JavaScriptCore

    JavaScriptCore是苹果在iOS7时新推出用以实现JS和iOS代码交互的框架,十分简单高效。以下两篇在网上搜到关于JavaScriptCore用法的博文,写得十分详细,照着做基本没什么问题。

    iOS js oc相互调用(JavaScriptCore) - - 博客频道 - CSDN.NET

    iOS js oc相互调用(JavaScriptCore)(二) - - 博客频道 - CSDN.NET

    需要特别说明的一点是:第二篇博文是介绍JS调用OC的方法,有两种做法:

    第一种是直接调用方法通过iOS的block回调,这种做法虽然简单易懂,也可以传值,但是不能传递返回值,而我那时刚好有返回值的需求,所以我参照的第二种方法,这种方法的原理就是把JS的对象和我们本地建立的对象捆绑在一起,并调用相应的方法。这种方法虽然代码写得比较复杂,但是调用方法十分畅顺,能够正常传值和返回值,推荐!!!

    最后关于这个框架最需要强调的一点是:JS调用OC时,是需要等浏览器加载完页面后才能进行交互(坑!!!),而安卓是不需要的,当时我做到这里也被坑了,明明我自己写的demo是可以交互的(用按钮点击触发交互,显然这是在页面加载后触发的),但加载后台的页面就不行,因为我们的后台页面是在加载的过程中就想调用OC的方法,所以不能实现正常交互,而我们后台当时的做法就是把方法延时执行,但是这样不仅会影响用户体验也会受到网速的影响,因此不太稳定,不建议这样做。

    优秀的第三方框架--WebViewJavascriptBridge

    先奉上这个框架的GitHub地址GitHub - WebViewJavascriptBridge 

    事实上关于JS和OC的交互,上Google一查,很多人都在推荐用这个框架,我下载了demo,看了一下,确实是十分好用,同时支持UIWeView和WKWebView,无论是JS调用OC还是OC调用JS,都可以正常传值返回值;而且在页面加载时只要JS代码被运行就可以进行交互,上面遇到的缺点和坑在这里都被掩埋的,真是良心之作,好有真诚!!!具体用法在GitHub上说的挺详细的,下面大概说一下吧:

    JS代码:

    先把下述代码复制到JS

    调用的代码:

    OC代码:

    注册一个WebViewJavascriptBridge的对象

    调用的代码:

    无论是OC和JS,主动调用的一方都是先调用callHandler方法,而被调用的一方则在registerHandler方法里响应,看起来很清晰明了吧。

    如果真的要用到这个框架,除了iOS的开发人员外,也要让后台的人了解这个框架,并在合适的位置注入上述JS代码,虽然是比较麻烦,但是这个框架确实挺好用,推荐指数5颗星!!!

    结束

    方法是多样的,至于到底使用哪种方法,还要看各自的产品需求,不管是黑猫还是白猫,能捉到老鼠的就是好猫,哈哈。以上就是我做这个功能时的个人总结,浅薄之见,多多包涵。最后送上座右铭:学习之路,与君共勉。

    相关文章

      网友评论

      • George不资深:请问我想 用js 调用oc方法,然后alert 出来结果,怎么处理呢?
        ccc小yyy:首先,你是用哪个框架做交互,不同的框架代码不一样;其次你这个alert结果是想在js中alert还是OC中alert?
      • GGG_GGG:有一个问题,现在我们这边ios和安卓都采用那种给js注入ios原生对象的方法,而且遇到的坑跟你一样,也采用的延迟加载,很不严谨. 但是我们要是替换WebViewJavascriptBridge,那前端同志写js交互代码的时候就得区分ios和安卓了,是吧...
        ccc小yyy:WebViewJavascriptBridge安卓也有一套对应框架,可以实现跨平台js代码的统一
      • d60e80cd17d5:如果iOS和后台用这个,android和js交互要怎么用这套呢?
        Lmsgsendnilself:具体 通信方式android没这么复杂
        js端分别处理下即可
        记得iOS处理的时候外套一个接口
        这样能保证window.interface 这种方式兼容两个端
      • CR汀:1120134596
      • CR汀:楼主能加QQ聊么,怎么js调用微信支付
        CR汀:@曹小猿 学习能力比较差
        ccc小yyy:@CR汀 上面写的很清楚了,你好好看看吧
      • c492bbbc5041:用javascriptCore,刷新web之后js交互不了了,请问怎么回事
        ccc小yyy:@G_J 对,用javascriptCore是必须这样
        c492bbbc5041:@曹小猿 必须是web加载后再交互才可以吗
        ccc小yyy:@G_J 有等web页面加载后才交互吗
      • 流星大石头:写的非常给力,非常受益
      • 欧辰_OSR:写的很不错 :+1:
      • 欧辰_OSR:挺好的
      • 名字太多不会起:哎,我现在就是这个坑啊,JS想在加载网页过程中调用OC方法,传的全是nil,WKWebView ,也是这个样子么,在加载网页完成后调用OC 的吗?
        Lmsgsendnilself:https://lmsgsendnilself.github.io/blog/2016/01/23/uiwebviewyu-jshun-bian-you-hua/中的优化第一点当初始化加载JS代码时,这需要一些时间,而在此加载过程中,很有可能iframe已经发送了一些URL请求,那么,如果不做任何处理,将会使得所有url请求处理涉及到的数据为nil。 为了应对此问题,首先在js端的代码文件加载完成时触发一个url请求,在OC端则利用一个标志位isReady,根据url的内容使其标志是否加载完毕。在OC端利用一个可变缓存数组cacheJavaScriptCommands,将isReady为NO时所有的指令依次添加其中,等UIWebview初始化JS代码加载完成准备好后,再按照顺序依次执行缓存中的JS指令。
        Lmsgsendnilself:这篇博客的优化方案 能解决这个问题。
        UIWebview与JS混编优化
        https://lmsgsendnilself.github.io/blog/2016/01/23/uiwebviewyu-jshun-bian-you-hua/
        ccc小yyy:@名字太多不会起 用WebViewJavascriptBridge吧,可以解决这个问题
      • 水户洋平_Psist:非常棒 虽然有些地方还不懂 但是思路清晰 支持。

      本文标题:JS和OC的交互(基于UIWebView)

      本文链接:https://www.haomeiwen.com/subject/jzxglttx.html