程序员人生 网站导航

UIWebView和js交互

栏目:综合技术时间:2015-08-10 08:51:20
    之前做过1个项目,里面触及到显示公式之类的东西就必须要在项目里面嵌入网页,最麻烦的就是网页需要在本地自己拼凑成html,然后再使用UIWebView加载出来,这里面就触及到了1些关于OC和JavaScript交互的问题,对第1次接触这些的人,还是会走1些弯路。我在此把自己学习的分享出来,希望帮到1些人。

分两部份介绍,第1部份是加载本地网页。然落后行交互。第2部份是加载服务器的网页落后行交互。

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

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

  第1种

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

第2种

<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>

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

1.在界面里面添加1个1个UIWebView和1个按钮,按钮用于OC对网页发起操作 
currentY = self.navigationController.navigationBar.frame.size.height; screen = [UIScreen mainScreen].bounds.size; _webView = [[UIWebView alloc] initWithFrame:CGRectMake(0, currentY, screen.width, screen.height⑴00)]; self.automaticallyAdjustsScrollViewInsets = NO; _webView.delegate = self; // _webView.backgroundColor = [UIColor clearColor]; [self.view addSubview:_webView]; UIButton * button = [[UIButton alloc] initWithFrame:CGRectMake(50, screen.height⑸0, screen.width⑴00, 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]; // 从本地加载1个html文件。 [self.webView loadHTMLString:htmlString baseURL:baseURL];
这类方式把html当作文件加载
NSString * htmlPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"index.html"]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:htmlPath]]];
这类方法则是相当于发起1个要求
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; }
这个返回值1定要是YES的,否则加载不出来,对上面这个拜托方法是用来处理js发起的要求,对要求的判断,也是可使用两种不同的方法。上面的源码里面都已给出。个人更喜欢第1种,如果有多种不同的要求,又有很对子要求的话第2种应当好1些。
//开始要求调用的方法,可以加个唆使器 - (void)webViewDidStartLoad:(UIWebView *)webView{ } //结束要求调用的方法,可以加个唆使器 - (void)webViewDidFinishLoad:(UIWebView *)webView{ } //加载失败的方法 - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error{ NSLog(@"error是%@",error); } 4.oc对js交互 oc对html进行修改的话,我们使用1个方法就能够。stringByEvaluatingJavaScriptFromString,苹果也就只给了这1个方法。 - (void)appTojs{ NSString * js = @" var p = document.createElement('p'); p.innerText = '增加1行';document.body.appendChild(p);"; [self.webView stringByEvaluatingJavaScriptFromString:js]; }

2 加载网络服务器的页面(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代码注入到原网页中
不的不提示1下上面的js代码,如果你不是很熟习的话,修改1些参数就能够,OC里面要不把js弄错还真是困难,那末多引号,少1个都有可能出问题。反正我弄了1个下午。改来改去总是出错。可能和我不太熟习JS有很大的关系。这个注入以后,其他的个本地加载没多大区分了。不过有些网页是加了限制不让注入的。团队在开发的时候肯定需要调和好。我demo里面是使用了百度。代码是进去了,但是还是运行不了,百度应当是拦截了它。
因而Demo就是现在这个样了,我用了1个本地的页面的,但是和从服务器加载出来的差不多。里面我并没有提早写好要求的地址之类的。 是使用OC给html注入的。

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

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

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐