iOS开发 UIWebView+JavaScript 交互总结

算是个人项目经验的,印象比较深的Web+JS交互的使用

iOS原生应用与Web页面元素交互方式有很多,JavaScriptCore、拦截协议、第三方框架WebViewJavaScriptBridge、iOS8之后的WKWebView等;

简要记录下之前开发用到的两种方式:

1. 劫持页面加载,从 UIWebVIew 的 shouldStartLoadWithRequest 方法中拦截RequestURL 判断加载项,代码简要:

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

{

NSString *urlStr = [[request URL] absoluteString];

// 加载的url 关键词需要同后台约定

NSRange range_keyWord = [urlStr rangeOfString:@"opengood://"];

if (range_keyWord.length > 0) {

  [self doSomeThing];

  }

return YES;

}

2. iOS7之后水果公司推出的 JavaScriptCore 框架,交互起来hin方便

需要注意的是JS调用的方法名等需要同前端的同事沟通好,最好由前端提供给你。

浅显的说,这个方式等同于将当前ViewController 注入到web的context中,不同webClick都能够有不同的JS方法与VC上面的代理方法相对应,

例:

  Web端

   javaScript控件的点击事件约定触发 'task.openNewWeb('urlStr')'

  “task”这个东西在web源码中并没有什么实际意义 它只相当于iOS端的某个viewController的占位符号

iOS端代码:

#import <JavaScriptCore/JavaScriptCore.h>

UIWebView 代理方法中将当前控制器动态注入js中

- (void)webViewDidStartLoad:(UIWebView *)webView {

   //首先创建JSContext 对象(此处通过当前webView的键获取到jscontext)

  JSContext * context =[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

  // 控制器self 填充web中预留的占位符‘task’

  self.context[@"task"] = self;

// 这时候javaScript控件的点击事件约定触发 'task.openNewWeb('urlStr')'

// 那么在OC语法中相当于 [self openNewWeb:urlStr];

   self.context.exceptionHandler = ^(JSContext *context, JSValue *exceptionValue) {

context.exception = exceptionValue;

NSLog(@"异常信息:%@", exceptionValue);

};

}

******** ⚠️ 注意:WEB JS交互crush

/*

*    web点击事件 'task.click()' ,OC中必须要有对应的方法声明和实现,否则无法响应交互或导致crush

*     而且,在iOS10 以后 貌似加强了调度表查询机制,所以声明OC方法名的时候注意重复问题,

*    例如 openWeb:(int)index (NSString *)url 与 openWeb:(NSString *)url 形参数量存在差异,视为两个不同方法

*    因为在OC消息传递机制中,self.openNewWeb() 首先是通过self 查找保存本身所有selector的调度表

*    若self的selectorNameList中并未找到js调用的task.selectorName ,则通过self的isa定位到superClass,继续从super中的函数调度表 selectorNameList查询

*     superClass中仍未查到则继续根据其isa顺藤摸瓜找到super的元类继续查找 如果元类中还没有 抛出异常>> crush.nice - -b

*/    

所以对于上面拦截web加载的方式,JavaScriptCore 的另一个优点就是提升代码可读性。。。

由于项目代码内部有涉及到公司业务不方便贴出来,给大家提供两个之前调研过的连接,里面有详尽的JavaScriptCore 使用

链接1

http://mp.weixin.qq.com/s?__biz=MzAxMzE2Mjc2Ng==&mid=401786074&idx=1&sn=f03d52e7b4f980d694ed4a6b0e808d3b&scene=23&srcid=0309JfhgdIYEJ4vg1YY3OD2T#rd

链接2

http://mp.weixin.qq.com/s?plg_nld=1&plg_auth=1&plg_nld=1&plg_dev=1&plg_uin=1&plg_usr=1&plg_vkey=1&plg_nld=1&plg_uin=1&mid=403853462&plg_nld=1&idx=1&scene=23&plg_auth=1&__biz=MjM5Nzc1MzU2NA%3D%3D&plg_dev=1&srcid=0308AYX0Hpyq3w7TEdwDQ8z8&plg_usr=1&sn=f7437fe6fa45e62d86c026efa4aa1645&plg_vkey=1#rd

在很多页面涉及web交互时,就要频繁调用JS与ViewController关联的方法

这个之前写的一个web类目,提供下载链接,欢迎修改和完善

http://pan.baidu.com/s/1eRSt6p0