众所周知,随着硬件水平的发展,HTML5 与原生 APP 性能差距不断缩小,正在互联网科技领域扮演者越来越重要的角色。作为一种能很大程度上节约成本的技术方案,通过 HTML5 及 JS 实现的跨平台技术也越来越成熟。

作为一名普通的 iOS 开发者,我们在项目中也会或多或少的用到一些 JS 代码,如何实现 JS 和 OC 之间的交互常常是我们会面临的一个问题。最近一段时间,笔者最近由于工作需要,研究了很多 iOS 下与 JS 交互的问题,接下来我会把这个过程中遇到的坑和积累的经验分享给大家。

第一个要说的就是如何在 OC 下调用 JS,这个很简单,想必大家都会不约而同的回答出,使用 UIWebView 的stringByEvaluatingJavaScriptFromString 方法。

接下来我从自己的实际经历聊一下如何使用stringByEvaluatingJavaScriptFromString调用javascript

1、 stringByEvaluatingJavaScriptFromString只能在主线程执行。

比如,假如你调用了下面这段代码:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
[webView stringByEvaluatingJavaScriptFromString:@"aaa"];
});

程序就会崩溃,并打出下面的log:

崩溃产生的原因是你在主线程以外的线程调用了UIKit,系统在执行stringByEvaluatingJavaScriptFromString的时候调用了UIKit里的一些方法,所以不允许在主线程之外的线程去调用这个方法。

解决方法也有很多可以用

[webView performSelectorOnMainThread:]

或者

dispatch_sync(dispatch_get_main_queue(), ^{
[webView stringByEvaluatingJavaScriptFromString:@"aaa"];
});

2、简单调用系统提供的javascript方法

对于一些简单的javascript系统方法,我们可以通过stringByEvaluatingJavaScriptFromString做一下简单的调用,并取得返回值。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"];
NSLog(@"%@", title);
}

3、在加载的html里插入代码,并执行

比如我用下面的代码插入了一个名叫alertTest的函数到javascript里实现在页面中显示alert的功能。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
[webView stringByEvaluatingJavaScriptFromString:
@"var script = document.createElement('script');"
"script.type = 'text/javascript';"
"script.text = \"function alertTest(str) { "
"alert(str)"
"}\";"
"document.getElementsByTagName('head')[0].appendChild(script);"];
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"alertTest('%@');", @"test"]];
}

值得注意的一点是

- (void)webViewDidFinishLoad:(UIWebView *)webView方法指的并不是webview完全加载完毕,而是指网页中一个iframe或frame加载完毕,也就是说假如网页里有多个frame,那么webViewDidFinishLoad会执行多次。这就会导致上面插入代码的方法会执行多次,stringByEvaluatingJavaScriptFromString执行JS是一笔不小的时间开销,所以我们应该尽量减少使用它去执行复杂的JS代码。

我使用了下面的方式检查是否已经插入并执行了这个函数,typeof alertTest检查了alertTest这个函数是否存在,若存在则不执行if里面的代码插入和代码执行语句。

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
BOOL isExist = [[webView stringByEvaluatingJavaScriptFromString:@"typeof alertTest == \'function\';"] isEqualToString:@"true"];
if (!isExist) {
[webView stringByEvaluatingJavaScriptFromString:
@"var script = document.createElement('script');"
"script.type = 'text/javascript';"
"script.text = \"function alertTest(str) { "
"alert(str)"
"}\";"
"document.getElementsByTagName('head')[0].appendChild(script);"];
[webView stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"alertTest('%@');", @"test"]];
}
}

OneAPM Mobile Insight,监控网络请求及网络错误,提升用户留存。访问 OneAPM 官方网站感受更多应用性能优化体验,想阅读更多技术文章,请访问 OneAPM 官方技术博客

本文转自 OneAPM 官方博客

UIWebView 与 JS 交互(1):Objective-C 调用 Javascript的更多相关文章

  1. UIWebview于JS交互

    最近使用火车票网的限行网页,但是广告以及头部nav和地步footer都是我们现在所不需要的,所以决定使用js交互,下面所有代码都写在 webViewDidFinishLoad 里面 1.查看原网址的源 ...

  2. VC与JavaScript交互(三) --- CWebPage类调用javascript函数(给js函数传参,并取得返回值)

    ①需要一个别人写好的类CWebPage,将其对于的两个文件WebPage.h和WebPage.cpp添加到工程中. ②添加WebBrowser控件,在视图/对话框类的头文件中#include &quo ...

  3. UIWebView和Js交互

    在日常的ios项目开发中,我们经常会在原生应用中嵌入web页面,通常我们只是进行一个展示,没有其它的一些功能.但是也有一些项目中需要web页面中的html和native进行交互.但是ios sdk 并 ...

  4. iOS中UIWebView使用JS交互 - 机智的新手

    iOS中偶尔也会用到webview来显示一些内容,比如新闻,或者一段介绍.但是用的不多,现在来教大家怎么使用js跟webview进行交互. 这里就拿点击图片获取图片路径为例: 1.测试页面html & ...

  5. UIWebview与js交互[转]

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌入页面中,通过这个方法我们可以在iOS ...

  6. iOS中UIWebView使用JS交互

    iOS中偶尔也会用到webview来显示一些内容,比如新闻,或者一段介绍.但是用的不多,现在来教大家怎么使用js跟webview进行交互. 这里就拿点击图片获取图片路径为例: 1.测试页面html & ...

  7. uiwebview和 js交互框架

    WebViewJavascriptBridge

  8. UIWebView与JS的深度交互

    我要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的 HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img &g ...

  9. UIWebView与JS的深度交互-b

    要实现这样一个需求:按照本地的CSS文件展示一串网络获取的带HTML格式的只有body部分的文本,需要自己拼写完整的 HTML.除此之外,还需要禁用获取的HTML文本中自带的 < img > ...

随机推荐

  1. c# 委托与异步调用

    背景:在winform UI中,有时需要对控件进行比较频繁的刷新,如进度条.picturebox显示视频等.如果在主线程进行这些刷新操作,操作还未完成就将执行下一次刷新,程序将发生错误:如果只是创建另 ...

  2. Js替换地址栏参数

    开了博客竟然有9个月没在来写过了.真是惭愧.今天需要用到一个用js替换地址栏参数的的功能.就自己用JS自己写了一个简单的函数.贴出来仅供大家参考.代码都写了注释.如下: /* js替换URL参数值,无 ...

  3. make fontconfig 时出现No package ‘libxml-2.0′ found的解决方法

    这里显示一个错误信息:checking for LIBXML2… configure: error: Package requirements (libxml-2.0 >= 2.6) were ...

  4. Java的基本数据类型

    java的基本数据类型是四类八种: 整型 byte  1字节  8位 short 2字节 16位 int 4字节 32位 long   8字节 64位 在hibernate自动映射中会根据数字长度,选 ...

  5. java中进制之间的转换

    //十进制转其他进制 Integer.toHexString(10); //将10转换为十六进制,返回字符串类型 Integer.toOctalString(10); //将10转为八进制,返回字符串 ...

  6. 程序员面试题精选100题(33)-在O(1)时间删除链表结点[数据结构]

    作者:何海涛 出处:http://zhedahht.blog.163.com/ 题目:给定链表的头指针和一个结点指针,在O(1)时间删除该结点.链表结点的定义如下: struct ListNode { ...

  7. OpenJudge 2737 大整数除法

    链接地址:http://bailian.openjudge.cn/practice/2737/ 题目: 总时间限制: 1000ms 内存限制: 65536kB 描述 求2个大的正整数相除的商 输入 第 ...

  8. hdu 5055 Bob and math problem

    先把各个数字又大到小排列,如果没有前导零并且为奇数,则直接输出.如果有前导零,则输出-1.此外,如果尾数为偶数,则从后向前找到第一个奇数,并把其后面的数一次向前移动,并把该奇数放到尾部. 值得注意的是 ...

  9. javascript 弹出的窗口返回值给 父窗口

    直接上代码,有些地方可以用到: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <H ...

  10. VS2010开发环境最佳字体及配色方法

    Fixedsys Excelsior 3.01 1. 首先下载字体:http://www.fixedsysexcelsior.com/   脚本之家字体下载 2. 安装字体:control panel ...