IOS和JS的交互,看这一篇文章就够了

创作不易,请珍惜,之后会持续更新,不断完善
Demo地址

目录

  • WKWebView使用、JS的交互

WKWebView使用、JS的交互

演示(本来想贴张GIF作为演示流程的,害,太模糊不清了还是算了,话说简书写起来不方便呀,图片大小清晰度也挺难看的,吐槽下),顺便列举下控制台的所有输出作为例证,相关输出用到的地方在代码注释处有写

控制台输出

创建WKWebView

    WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];    // 创建wkWebView    self.wkWebView = [[WKWebView alloc] initWithFrame:self.view.frame configuration:configuration];    self.wkWebView.UIDelegate  = self;    self.wkWebView.navigationDelegate = self;    [self.view addSubview:self.wkWebView];

WKNavigationDelegate

页面加载完成之后调用, 定义一个全局变量 arr

- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{    // 导航栏标题    self.title = webView.title;    // 定义一个全局变量 arr    NSString *jsStr = @"var arr = [5, '谢佳培', 'xiejiapei']; ";    [self.wkWebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {        // 页面加载完成之后调用, 定义一个全局变量 arr: (null)----(null)        NSLog(@"页面加载完成之后调用, 定义一个全局变量 arr: %@----%@",result, error);    }];}

拦截网页的跳转链接: 在发送请求之前,决定是否跳转,点击提交按钮的时候会调用该方法

提交.png

- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler{    // URL = @"lgedu://jsCallOC?username=Cooci&password=123456"    // 获取请求的URL    NSURL *URL = navigationAction.request.URL;    // 获取URL Scheme,其作用为方便app之间互相调用而设计的    NSString *scheme = [URL scheme];

    // 拦截lgedu    if ([scheme isEqualToString:@"lgedu"])    {        // url是地址, 在某个主机目录下的文件的唯一标识符(统一资源定位符url)        // domain是域名, 比如baidu.com就是域名,而其对应的ip地址指向了百度的服务器        // host是主机, 默认情况http协议是80端口 https协议是443端口        NSString *host = [URL host];

        // 主机名为jsCallOC        if ([host isEqualToString:@"jsCallOC"])        {            // 解析URL            NSMutableDictionary *temDict = [self decoderUrl:URL];            NSString *username = [temDict objectForKey:@"username"];            NSString *password = [temDict objectForKey:@"password"];            // 用户名和密码:谢佳培------123456            NSLog(@"用户名和密码:%@------%@",username,password);        }        else        {            NSLog(@"不明地址 %@",host);        }        // 不允许跳转        decisionHandler(WKNavigationActionPolicyCancel);        return;    }    // 允许跳转    decisionHandler(WKNavigationActionPolicyAllow);}

解析URL地址,取得JS中的值

// 解析URL地址- (NSMutableDictionary *)decoderUrl:(NSURL *)URL{    // URL = @"lgedu://jsCallOC?username=谢佳培&password=123456"    // 分开参数    NSArray *params = [URL.query componentsSeparatedByString:@"&"];    NSMutableDictionary *tempDic = [NSMutableDictionary dictionary];

    for (NSString *param in params)    {        // 分开键值对        NSArray *dictArray = [param componentsSeparatedByString:@"="];

        if (dictArray.count 1)        {            /** 网络请求拼接中文参数,用户名登陆等很多地方会用到中文,UTF8编码显得颇为重要             *  编码:             *  NSString* hStr =@"你好啊";             *  NSString* hString = [hStr stringByAddingPercentEncodingWithAllowedCharacters:[NSCharacterSet URLQueryAllowedCharacterSet]];             *  NSLog(@"hString === %@",hString); // hString === %E4%BD%A0%E5%A5%BD%E5%95%8A             *             *  解码:             *  NSString*str3 =@"\u5982\u4f55\u8054\u7cfb\u5ba2\u670d\u4eba\u5458\uff1f";             *  NSString*str5 = [str3 stringByRemovingPercentEncoding];             *  NSLog(@"str5 ==== %@",str5);// str5 ====如何联系客服人员?             */            // 取值, 中文解码            NSString *decodeValue = [dictArray[1] stringByRemovingPercentEncoding];            // 解码后放入tempDic            [tempDic setObject:decodeValue forKey:dictArray[0]];        }    }

    return tempDic;}

JS中相关代码如下

        >input type="button" value="提交" onclick="submit()" /br /<        function submit(){            alert('点击了提交按钮,调用loadURL方法获得URL');            loadURL("lgedu://jsCallOC?username=谢佳培&password=123456");        }

        function loadURL(url) {            var iFrame;            iFrame = document.createElement("iframe");            iFrame.setAttribute("src", url);            iFrame.setAttribute("style", "display:none;");            iFrame.setAttribute("height", "0px");            iFrame.setAttribute("width", "0px");            iFrame.setAttribute("frameborder", "0");            document.body.appendChild(iFrame);            iFrame.parentNode.removeChild(iFrame);            iFrame = null;        }

WKUIDelegate

使用OC样式的弹出警告框,覆盖JS的丑陋样式

// 警告框- (void)webView:(WKWebView *)webView runJavaScriptAlertPanelWithMessage:(NSString *)message initiatedByFrame:(WKFrameInfo *)frame completionHandler:(void (^)(void))completionHandler{    // 使用OC样式的弹出警告框,覆盖JS的丑陋样式    UIAlertController *alert = [UIAlertController alertControllerWithTitle:@"提醒" message:message preferredStyle:UIAlertControllerStyleAlert];    UIAlertAction *knowAction = [UIAlertAction actionWithTitle:@"知道了" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {        // 回调完成        completionHandler();    }];    [alert addAction:knowAction];    [self presentViewController:alert animated:YES completion:nil];}

OC 调用 JS方法

通过  evaluateJavaScript调用了JS中的showAlert方法
演示图:

代码片段:OC

    // JS方法    // alert('我是一个可爱的弹框 \n'+messgae+'\n'+arr[1]);    // arr[1]来自在我们在页面加载完成后定义的全局变量arr    // msg: 我是一个可爱的弹框 登陆成功 谢佳培    NSString *jsStr = [NSString stringWithFormat:@"showAlert('%@')",@"嗨,这是通过OC调用showAlert方法哦"];

    // OC 调用 JS方法    [self.wkWebView evaluateJavaScript:jsStr completionHandler:^(id _Nullable result, NSError * _Nullable error) {        // OC 调用 JS方法: token----(null)        // Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,        // 当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。        // 使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。        NSLog(@"OC 调用 JS方法: %@----%@",result, error);    }];

代码片段:JS

        function showAlert(messgae){            alert('我是一个可爱的弹框 \n'+messgae+'\n'+arr[1]);            return "token";        }

WKUserContentController

调整按钮大小适应APP页面

configuration.userContentController = [self wkwebViewScalPreferences];

// 调整按钮大小适应APP页面- (WKUserContentController *)wkwebViewScalPreferences{    // js注入: json调整按钮大小脚本    NSString *jScript = @"var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);";

    /** WKUserScript就是帮助我们完成JS注入的类,它能帮助我们在页面填充前或js填充完成后调用     * 参数1:脚本的源代码     * 参数2:脚本应注入网页的时间,是个枚举,End表示:在文档完成加载之后,但在其他子资源完成加载之前插入脚本     * 参数3:是否加入所有框架,还是只加入主框架     */    WKUserScript *wkUserScript = [[WKUserScript alloc] initWithSource:jScript injectionTime:WKUserScriptInjectionTimeAtDocumentEnd forMainFrameOnly:YES];    WKUserContentController *wkUserContentController = [[WKUserContentController alloc] init];    [wkUserContentController addUserScript:wkUserScript];

    return wkUserContentController;}

MessgaeHandle

JS相关代码: 发送了消息

        >input type="button" value="messgaeHandle" onclick="messgaeHandle()" /<>br /<        function messgaeHandle(){            // js -- android            alert('给messageHandlers页面发送了“青春气息”');            window.webkit.messageHandlers.messgaeOC.postMessage("青春气息");        }

viewWillAppear中监听消息,但是注意在viewWillDisappear需要移除,否则会造成循环引用,不会调用到dealloc方法

// 循环引用:self - webView - configuration - userContentController - self- (void)viewWillAppear:(BOOL)animated{    [super viewWillAppear:animated];

    // 添加scriptMessageHandler到所有的frames中,    // html5中需要添加window.webkit.messageHandlers.>name<.postmessage>messageBody    [self.wkWebView.configuration.userContentController addScriptMessageHandler:self name:@"messgaeOC"];}// 需要根据name移除所注入的scriptMessageHandler来打破循环引用, 否则不会调用到dealloc方法- (void)viewWillDisappear:(BOOL)animated{    [super viewWillDisappear:animated];    [self.wkWebView.configuration.userContentController removeScriptMessageHandlerForName:@"messgaeOC"];}- (void)dealloc{NSLog(@"dealloc:溜了溜了");}

WKScriptMessageHandler

WKWebView收到ScriptMessage时回调此方法

// WKWebView收到ScriptMessage时回调此方法- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message{    if (message.name)    {        // OC 层面的消息    }    // message == messgaeOC --- 青春气息    NSLog(@"消息是:%@ --- %@",message.name,message.body);}

js层级选择框样式_IOS和JS的交互,看这一篇文章就够了相关推荐

  1. js层级选择框样式_【JavaWeb】85:jQuery的各种选择器

    今天是刘小爱自学Java的第85天. 感谢你的观看,谢谢你. 话不多说,开始今天的学习: 选择器的作用是什么? 可以快速准确地定位我们所需要的标签. 刚学CSS的时候,觉得CSS选择器也太多了吧,直到 ...

  2. 浏览器滚动条css样式设置,看这一篇文章就够了!

    一 前言 在CSS 中,如果我们在块级容器上设置了属性: overflow:scroll /* x y 方向都会*/ 或者 overflow-x:scroll /*只是x方向*/ 或者 overflo ...

  3. input选择框样式修改与自定义

    html自带的选择框样式不好看,并且在ios设备上丑的罚款.所以一般都是自定义样式: 原理:将原来默认的input选择框隐藏,然后控制label的:before与:after,配合矢量图标或者图片来实 ...

  4. 用jquery修改默认的单选框radio或者复选框checkbox选择框样式

    默认的radio和checkbox选框很难看.我去看了一下qq注册的页面.发现单选和复选框并没有用<input>,居然是用是A标签.然后用css背景图片展示选择框,用JavaScript控 ...

  5. mock.js如何使用?简单易懂,一学就会,一篇文章即可出师

    1,mock.js是什么? mockjs是生成随机数据的一款前端工具,用来模拟 Ajax 请求,生成并返回模拟数据 2,为什么用mockjs? 当程序员做项目开发时,前端工程师要请求后端做好的数据时, ...

  6. js如何修改html样式,怎么用js改变css样式?

    怎么用js改变css样式?下面本篇文章给大家介绍一下使用JavaScript改变css样式的方法.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助. 怎么用js改变css样式? 1.通过 ...

  7. html input选择框样式修改,关于type=file的input框样式修改小结

    关于type="file"的input是啥? 这个是啥我觉得没必要再说了,反正大家都知道,然后在现在有各种手机的时代,还可以通过直接拍照的方式来上传,反正比以前好玩多了. 上传按钮 ...

  8. 吉他新手防踩雷,告别吉他选择困难症!初学者吉他推荐!看这一篇就够了!

    吉他新手扫盲 | 告别吉他选择困难症+初学者吉他推荐!一篇全搞定! 1.考虑预算 2.合板.面单.全单 3.手感弦距 4.音色.音准 5.桶型选择 6.吉他保养 对于吉他的挑选,各位新手小可爱们总是有 ...

  9. html文本框自动赋值,js给文本框赋值 value与innerHTML

    赋值操作: document.getElementById("testId").value="hello"; value与innerHTML的区别 上面的val ...

最新文章

  1. Java调用ocx控件以及dll
  2. tesseract-ocr tips
  3. ----icon moon追加新字体图标----
  4. apt get php mysql_Ubuntu10用apt-get配置apache+php+mysql(轉)
  5. 该如何弥补 GitHub 功能缺陷?
  6. 关于tomcat 中的 tomcat-users.xml 配置不生效原因
  7. 叶脊网络拓扑(leaf-spine)
  8. 怎样看oracle有没有监听,Oracle数据库学习_Windows系统查看Oracle数据库监听状态的方法...
  9. Laravel学习记录--查询构造器
  10. 如何选择适合你的兴趣爱好(六十一),瓷器
  11. java的json解析_java中json的使用和解析
  12. allegro 封装shape焊盘问题 Unable to load shape symbol
  13. 《论文阅读》Knowledge-Enriched Transformer for Emotion Detection in Textual Conversations
  14. 数据库操作--已更新或删除的行值要么不能使该行成为唯一行,要么改变了多个行
  15. 51单片机数码管滚动显示学号_单片机数码管显示0到9程序代码
  16. Linux磁盘挂载问题 ***is apparently in use by the system; will not make a filesystem here!
  17. 基于LC push的浏览器桌面提醒快速集成方案
  18. 可视化图形界面编程(Easyx联合c++的通讯录系统)
  19. 汽车散热器不同造型的注塑件管口密封方案
  20. SQL注入堆叠注入二次注入

热门文章

  1. 卡通风格的渲染【Unity Shader入门精要14.1】
  2. VB.NET 读写HTML 文件,VB.Net读取和写入文本文件
  3. vbox 虚拟机访问网络,各个虚拟机实现互通
  4. 数据仓库灵魂30问之数仓有哪几种建模思想?
  5. Android 6.0: 动态权限管理的解决方案
  6. 【leetcode】75.颜色分类(多种解法,超详细图文解析)
  7. 帝国php分页,解决帝国CMS自动分页的问题
  8. JVM-XX:NewRatio 、-XX:SurvivorRatio 参数的含义
  9. 第18期基于SpringBoot仓库管理系统
  10. 四川省、成都市国际、国家、行业标准制定项目申请材料条件及认定奖励补助