iOS使用UIWebView和原生交互

来源:互联网 发布:大数据行业是干什么的 编辑:程序博客网 时间:2024/06/06 20:20
    之前做过一个项目,里面涉及到显示公式之类的东西就必须要在项目里面嵌入网页,最麻烦的就是网页需要在本地自己拼凑成html,然后再使用UIWebView加载出来,这里面就涉及到了一些关于OC和JavaScript交互的问题,对于第一次接触这些的人,还是会走一些弯路。我在此把自己学习的分享出来,希望帮到一些人。

分两部分介绍,第一部分是加载本地网页。然后进行交互。第二部分是加载服务器的网页后进行交互。

一  加载本地网页(demo下载地址}

  加载本地网页的话,由于网页都是自己写,我们可以把需要的请求参数都提前写好。这样在OC代码里面就可以直接的和网页交互。
  OC和js交互的原理是网页发起一个请求,然后WebView截获这个请求,对于这个请求的话可以是很多种的。我的Demo里面也总结了两种不同的方法。

  第一种

<script type="text/javascript">function sendCommand(cmd,param){    var url="zjq:"+cmd+":"+param;    document.location = url;}</script>

第二种

 <script language="javascript">            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就没用了,所以把它从dom上移除掉                iFrame.parentNode.removeChild(iFrame);                iFrame = null;            }            function check() {                loadURL("zjq:zjqjjqzjq");            }   </script>

用的比较多也比较简洁的是第一种,第二种的话是发起一个假的请求,一句话,都是为了网页能够刷新一下,WebView的委托才会被调用,才能够拦截到请求,然后做出相应的处理。

1.在界面里面添加一个一个UIWebView和一个按钮,按钮用于OC对网页发起操作 
currentY = self.navigationController.navigationBar.frame.size.height;    screen = [UIScreen mainScreen].bounds.size;    _webView  = [[UIWebView alloc] initWithFrame:CGRectMake(0, currentY, screen.width, screen.height-100)];       self.automaticallyAdjustsScrollViewInsets = NO;     _webView.delegate = self;//    _webView.backgroundColor = [UIColor clearColor];    [self.view addSubview:_webView];    UIButton * button  = [[UIButton alloc] initWithFrame:CGRectMake(50, screen.height-50, screen.width-100, 30)];    [button addTarget:self action:@selector(appTojs) forControlEvents:UIControlEventTouchUpInside];    [button setTitle:@"app向网页发送消息" forState:UIControlStateNormal];    [button setBackgroundColor:[UIColor grayColor]];    [self.view addSubview:button];
2.加载html页面
加载页面的方式也很多
  NSString * path = [[NSBundle mainBundle] bundlePath];    NSURL * baseURL = [NSURL fileURLWithPath:path];    NSString * htmlFile = [[NSBundle mainBundle] pathForResource:@"Test" ofType:@"html"];    NSString * htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:(NSUTF8StringEncoding) error:nil];//    从本地加载一个html文件。    [self.webView loadHTMLString:htmlString baseURL:baseURL];
这种方式把html当作文件加载
   NSString * htmlPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"index.html"];    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]];
这种方法则是相当于发起一个请求
3.实现委托函数(js对oc交互)
//当网页视图被指示载入内容而得到通知。应当返回YES,这样会进行加载- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{    NSURL *url = [request URL];    if ([[url scheme] isEqualToString:@"zjq"]) {        UIAlertView * alertView = [[UIAlertView alloc] initWithTitle:@"通知" message:[NSString stringWithFormat:@"%@%@",@"发起请求的url是:",[url absoluteString]]delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];        [alertView show];    }//多个//    NSString *requestString = [[request URL] absoluteString];//获取请求的绝对路径.//    NSArray *components = [requestString componentsSeparatedByString:@":"];//提交请求时候分割参数的分隔符//    if ([components count] > 1 && [(NSString *)[components objectAtIndex:0] isEqualToString:@"testapp"]) {//        //过滤请求是否是我们需要的.不需要的请求不进入条件//        if([(NSString *)[components objectAtIndex:1] isEqualToString:@"alert"])//    return YES; }
这个返回值一定要是YES的,否则加载不出来,对于上面这个委托方法是用来处理js发起的请求,对于请求的判断,也是可以使用两种不同的方法。上面的源码里面都已经给出。个人更喜欢第一种,如果有多种不同的请求,又有很对子请求的话第二种应该好一些。
//开始请求调用的方法,可以加个指示器- (void)webViewDidStartLoad:(UIWebView *)webView{   } //结束请求调用的方法,可以加个指示器- (void)webViewDidFinishLoad:(UIWebView *)webView{}//加载失败的方法- (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{    NSLog(@"error是%@",error);}4.oc对js交互oc对html进行修改的话,我们使用一个方法就可以。stringByEvaluatingJavaScriptFromString,苹果也就只给了这一个方法。- (void)appTojs{    NSString * js = @" var p = document.createElement('p'); p.innerText = '增加一行';document.body.appendChild(p);";    [self.webView stringByEvaluatingJavaScriptFromString:js];}

二 加载网络服务器的页面(demo下载地址)

 页面加载本身没有多大的难度,我这里主要介绍的是页面加载结束后,如何把我们的js代码注入到原来的html页面里面,我们才可以知道相应的请求的scheme等的相应信息。否则我的委托函数里面没有判断的根据嘛。
 - (void)webViewDidFinishLoad:(UIWebView *)webView{   NSString * string =  [webView stringByEvaluatingJavaScriptFromString:@"var script = document.createElement('script');"     "script.type = 'text/javascript';"     "script.text = \"function sendCommand(cmd,param){"     "var url='zjq:'+cmd+':'+param;"     "document.location = url;"     "}"     "var btn = document.getElementById('test');"     "btn.onclick = function(){"       "sendCommand('zjq','jump');"     "}\" ;"     "alert(script.text);"     "document.getElementsByTagName('html')[0].appendChild(script);"];    NSLog(@"返回的消息是%@",string);   //答应整个页面可以看到我们得代码是否加进去了    NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];    NSString *text = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.innerHTML"];    NSLog(@"url是,%@,text%@",currentURL,text);}
   这里主要的去区别就是在加载结束后我得把我得js代码注入到原网页中
不的不提醒一下上面的js代码,如果你不是很熟悉的话,修改一些参数就可以,OC里面要不把js弄错还真是困难,那么多引号,少一个都有可能出问题。反正我弄了一个下午。改来改去总是出错。可能和我不太熟悉JS有很大的关系。这个注入之后,其他的个本地加载没多大区别了。不过有些网页是加了限制不让注入的。团队在开发的时候肯定需要协调好。我demo里面是使用了百度。代码是进去了,但是还是运行不了,百度应该是拦截了它。

于是Demo就是现在这个样了,我用了一个本地的页面的,但是和从服务器加载出来的差不多。里面我并没有提前写好请求的地址之类的。 是使用OC给html注入的。


有的同学遇到这样的需求,就是想要隐藏某个web的控件。

[webview stringbyevaluatejavascript:@"document.getElementById('').style.display='none'"];



  参考资料地址时间有些久我都不记得了,这里不在列出,谢谢前辈们,加了很多个人理解,总觉得还是有些问题。不足之处请批评指正。

  装载请著名原创地址 :http://blog.csdn.net/zhouzhoujianquan/article/details/45397945

0 0
原创粉丝点击