UIWebView---UIWebView和JavaScript交互

今天来学一下JS和iOS交互的

下面举个例子

要做出这样的效果



html页面代码

<!DOCTYPE html>
<html>
    <body>
        <h1 id="id1">I'm Html </h1>
        <button type="button" οnclick=clickMe()> Talk To iOS</button>
        <script>
<!--            第一种调用方式-->
            function clickMe() {
                window.location.href = "Gap:I'm iOS, copy that";
            }
        </script>
    </body>
</html>


从Html发消息到iOS端

先说说html5上的按钮点击
window.location.href = "Gap:I'm iOS, copy that";
这样会产生一次请求, 我们就可以截取到链接

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *path=[[request URL] absoluteString];
    NSLog(@"%@",path);
    if ([path rangeOfString:@"gap:"].location != NSNotFound) {
        NSString *str = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        self.iosLabel.text = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
        return NO;
    }
    return YES;
}


从ios端发送到Html

插一段js代码来改变id为“id1”的元素的文字修改掉
- (IBAction)talkToHtmlAction:(id)sender
{
    NSString *js = @"var label = document.getElementById('id1'); label.innerText= 'I receive Your Message'";
    // NSString *js = @"document.getElementById('id1').innerText='I receive Your Message'";
    [self.webView stringByEvaluatingJavaScriptFromString:js];
}

如果事情真的这么简单就好了

下面来说一些比较复杂的

UIWebView发起特殊请求的方式

<!DOCTYPE html>
<html>
    <body>
        <h1 id="id1">I'm Html </h1>
        <button type="button" οnclick=clickMe()> Talk To iOS</button>
        <script>
<!--            第一种调用方式-->
            function clickMe() {
               <span style="color:#ff0000;"> window.location.href = "Gap:I'm iOS, copy that";</span>
            }
        </script>
    </body>
</html>
这里是通过修改window.location.href(也可以用document.location)来发起一个特殊请求

但是如果你需要2次修改window.location.href那会怎么样呢 ?只有后面的那句才有用

function clickMe() {
                window.location.href = "http://www.w3school.com.cn";
                window.location.href = "Gap:I'm iOS, copy that";
            }
那我们该怎么办呢

把clickme()的函数里面的换掉 (参数要用UTF8编码一下)

 function clickMe() {
                // 简单传值
                // var text = "I'm iOS, copy that";
                
                // 传个json字符串过去
                var text = '{"length1":76,"length2":155,"length3":76,"length4":155,"length5":76}';
                var url = "gap:" + EncodeUtf8(text);
                
                // 顺序很重要
                loadURL(url);
                //window.location.href = "http://www.w3school.com.cn";
            }
         function loadURL(url) {
               window.location.href=url;
                var iFrame;
                iFrame = document.createElement("iframe"); 
                 iFrame.setAttribute("src", url);
                 iFrame.setAttribute("style", "display:black;"); 
                 iFrame.setAttribute("height", "100px"); 
                 iFrame.setAttribute("width", "100px"); 
                 iFrame.setAttribute("frameborder", "10"); 
                 document.body.appendChild(iFrame); 
                 // 发起请求后这个iFrame就没用了,所以把它从dom上移除掉 
                  iFrame.parentNode.removeChild(iFrame);  
                  iFrame = null;  
         }

 function EncodeUtf8(s1)
        {
            // escape函数用于对除英文字母外的字符进行编码。如“Visit W3School!”->"Visit%20W3School%21"
            var s = escape(s1);
            var sa = s.split("%");//sa[1]=u6211
            var retV ="";
            if(sa[0] != "")
            {
                retV = sa[0];
            }
            for(var i = 1; i < sa.length; i ++)
            {
                if(sa[i].substring(0,1) == "u")
                {
                    retV += Hex2Utf8(Str2Hex(sa[i].substring(1,5)));
                    if(sa[i].length>=6)
                    {
                        retV += sa[i].substring(5);
                    }
                }
                else retV += "%" + sa[i];
            }
            return retV;
        }



这样子的话既可以web跳界面又可以顺利的和ios交互

如果我想传递一些复杂一点的参数呢

可以直接传个json字符串过去

 var text = '{"length1":76,"length2":155,"length3":76,"length4":155,"length5":76}';
 var url = "gap:" + EncodeUtf8(text);
 loadURL(url);

接收参数的协议里面也要改

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSString *path=[[request URL] absoluteString];
    NSLog(@"%@",path);
    if ([path rangeOfString:@"gap:"].location != NSNotFound) {
        NSString *str = [path stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
        NSString *strDic = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
        NSData *data = [strDic dataUsingEncoding:NSUTF8StringEncoding];
        NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
        NSLog(@"dic:%@", dic);
        self.iosLabel.text = [str stringByReplacingOccurrencesOfString:@"gap:" withString:@""];
        return NO;
    }
    return YES;
}


常见的JS调用

(1)获取标题

NSString *title = [webview stringByEvaluatingJavaScriptFromString:@"document.title"];

(2)获取URL

NSString *url = [webview stringByEvaluatingJavaScriptFromString:@"document.location.href"];

一些注意事项

《参考自ios进阶开发》

同步和异步

UIWebView调用原生界面时是异步操作

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


原生界面调用UIWebView是同步 

[self.webView stringByEvaluatingJavaScriptFromString:js];//直接返回NSString

这一点要注意一下

线程阻塞

当oc调用stringByEvaluatingJavaScriptFromString时 可能是由于js是单线程的原因会阻塞js代码的执行

解决办法是js端用defer把iFrame的插入延后执行

主线程问题

由于stringByEvaluatingJavaScriptFromString必须在主线程执行,所以如果主线程执行时间过长就会阻塞UI的更新 我们应该尽量让js的代码执行时间短

第三方库

(1)WebViewJavascriptBridge
https://github.com/marcuswestin/WebViewJavascriptBridge
(2)cordova
http://cordova.apache.org/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值