UIWebView 与 JS 交互(1): stringByEvaluatingJavaScriptFromString方法的调用

 本文非原创,由于无法直接转载到此,所以直接粘过来收藏。

原文链接:http://blog.oneapm.com/apm-tech/534.html

作为一名普通的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"]];
    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值