美文网首页
OC WebView 与JavaScript 交互

OC WebView 与JavaScript 交互

作者: 乌龙谦 | 来源:发表于2016-01-18 19:30 被阅读1768次

    Native 开发 和 H5  谁优谁劣,不在这边展开讨论。目前的开发过程中经常会遇到 原生应用 和web 交互的 需求。接下来我们就聊聊吧。

    需求点

    首页 运营一个活动,一个大转盘,转呀转呀,送 各种礼品呐。一个人一天可以转三次,分享到社交软件增加一次抽奖机会。


    开始

    iOS 应用 和web 页面交互 有以下 几种方法:

    1、挺有名的第三方框架 WebViewJavaScriptBridge

    2、iOS7 之后自带的 JavaScriptCore

    3、据说还可以 拦截协议

    第一种 和 第三种方法 这里就不详细介绍了(其实是我不会!!!)

    方法一 作为 一个 知名的第三方框架,肯定会有 其他同行小伙伴介绍的,

    传送门 :http://kittenyang.com/webview-javascript-bridge/

    反正我也写不过他!

    我选择方法二!

    因为简单...

    JavaScriptCore框架

    JSContext:给JavaScript提供运行的上下文环境

    JSValue:JavaScript和Objective-C数据和方法的桥梁

    JSManagedValue:管理数据和方法的类

    JSVirtualMachine:处理线程相关

    JSExport:一个协议,接下来会介绍到

    直接看代码

    @interfaceTWWebViewController() <UIWebViewDelegate>

    @property(nonatomic,strong)UIWebView*webView;

    @property(nonatomic,strong)JSContext*jContext;

    @property(nonatomic,strong)TWWebCallBackFunctionHelper*helper;

    @end

    考虑到 需求经常变化,我用 TWWebCallBackFunctionHelper 统一处理 OC 和 JS 制定的 方法。

    - (void)viewDidLoad

    {

    [superviewDidLoad];

    self.helper= [[TWWebCallBackFunctionHelperalloc]init];[self.viewaddSubview:self.webView];[self.webViewloadRequest:[NSURLRequestrequestWithURL:[NSURLURLWithString:self.webUrl]]];

    }

    加载  webView  和生成  TWWebCallBackFunctionHelper 对象。

    #pragma mark - UIWebViewDelegate

    - (BOOL)webView:(UIWebView*)webView

    shouldStartLoadWithRequest:(NSURLRequest*)request

    navigationType:(UIWebViewNavigationType)navigationType

    {

    returnYES;

    }

    - (void)webViewDidStartLoad:(UIWebView*)webView

    {

    if(!_jContext) {

    self.jContext=

    [webViewvalueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

    self.jContext[@"toApp"] =_helper;

    }

    }

    - (void)webViewDidFinishLoad:(UIWebView*)webView

    {

    if(!self.webTitle.length) {

    //获取当前页面的title

    NSString*webTitle = [webViewstringByEvaluatingJavaScriptFromString:@"document.title"];

    self.title= webTitle;

    }

    }

    - (void)webView:(UIWebView*)webView didFailLoadWithError:(NSError*)error

    {

    NSLog(@"didFailLoadWithError = %@", error);

    }

    在 webView 开始加载的时候 获取 JavaScript 上下文,和前端的小伙伴约定 toApp 为回调对象名(也有一些叫法 桥梁对象 ),helper 为实现协议对象。

    接下来实现 TWWebCallBackFunctionHelper

    #import <JavaScriptCore/JavaScriptCore.h>

    @protocol webViewJsDelegate<JSExport>

    JSExportAs(sharered, -(void)sharered

    : (NSString *)url shareContent

    : (NSString *)content linkUrl

    : (NSString *)lUrl);

    @end

    JSExport 是 一个 协议, 自定义的  webViewJsDelegate 协议 需要遵守此协议。

    我们来看下  JSExportAs 宏定义

    PropertyName  类似 一个 key,和 对应的 例子里是 sharered,其 对应 要实现的方法是

    -(void)sharered:shareContent:linkUrl;其中 'key' 对应的 sharered 需要和 web 约定一致。

    //遵守 webViewJsDelegate 协议

    @interfaceTWWebCallBackFunctionHelper() <webViewJsDelegate>

    @end

    @implementationTWWebCallBackFunctionHelper

    - (void)sharered:(NSString*)url shareContent:(NSString*)content linkUrl:(NSString*)lUrl

    {

    //TODO:

    //实现业务逻辑,调起 分享 功能

    }

    @end

    好了,差不多就这样了,在运行过程中,偶现一个bug,点击分享 按钮没有 丝毫 反应,也就是 分享UI组件 没有 调用起来。这是什么鬼呀!

    好吧,直接断点 调试,-(void)sharered:shareContent:linkUrl 方法是跑到了,也就是 调用 UI 时没有 反应。考虑是不是线程问题,看了JavaStript 相关定义,果然,“avaScript引擎是单线程运行的”,“JavaStript调用本地方法是在子线程中执行的” ,so...

    - (void)sharered:(NSString*)url shareContent:(NSString*)content linkUrl:(NSString*)lUrl

    {

    //TODO:

    //实现业务逻辑,调起 分享 功能

    //主线程中去 刷新 UI 等功能

    dispatch_async(dispatch_get_main_queue(), ^{

    }

    });

    }

    结论

    这边只是简单的介绍 JavaScriptCore  最基础的 用法,很轻量。更多的 JavaScriptCore API 可以去查 苹果官方文档。另外在网上搜了下,发现一篇 类似 介绍 OC WebView 与JavaScript 交互 文章,除了 介绍JavaScriptCore  还介绍了 iOS8之后的WKWebView  和 第三点 拦截协议,介绍的都 比我 的详细,贴出来 给大家参考:http://www.jianshu.com/p/f896d73c670a?utm_campaign=hugo&utm_medium=reader_share&utm_content=note&utm_source=weibo

    相关文章

      网友评论

          本文标题:OC WebView 与JavaScript 交互

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