【iOS开发之OC和JS互调】

 1.OC中调用JS代码

  • 公司的移动端需要加载一个现有的网页,并且要在原网页要做一些小的调整,如将网页的标题改一下加载到手机的app上,此时就可以在app的oc代码中加入JS代码来实现。如下例子,我要加载一个鲜花网(http://www.xianhua.cn/m/)并把它原有的标题"手机鲜花网"改为"鲜花网".
  • 原网页如下

  • 代码如下,先在viewDidLoad中加载网页,并加上菊花,隐藏网页(因为直接加载处理的标题不是我们想要的),再到 webViewDidFinishLoad: 这个方法中将js代码写入到一个字符串,作为参数传入这个方法 stringByEvaluatingJavaScriptFromString: ,此时网页就被改了,最后停止菊花,显示网页。
 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     
 4     //加载HTML
 5     NSURL *url = [NSURL URLWithString:@"http://www.xianhua.cn/m/"];
 6     NSURLRequest *request = [NSURLRequest requestWithURL:url];
 7     [self.webView loadRequest:request];
 8     
 9     // 先将网页隐藏
10     self.webView.scrollView.hidden = YES;
11     self.webView.backgroundColor = [UIColor grayColor];
12     
13 //    // 加菊花
14     UIActivityIndicatorView *displayView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
15     self.displayView = displayView;
16     // 开始转圈
17     [displayView startAnimating];
18     displayView.center = self.view.center;
19     [self.webView addSubview:displayView];
20 }
21 
22 
23 #pragma - 代理方法
24 -(void)webViewDidFinishLoad:(UIWebView *)webView{
25    NSString *str = @"document.getElementById('header').getElementsByTagName('h1')[0].innerText = '鲜花网';""document.getElementsByClassName('detail_btns2')[0].remove();""document.getElementById('xiazaiapp').getElementsByTagName('a')[0].innerText = '下载大神6期鲜花网(www.6q.com)App';";
26     // 加载js代码
27   [webView stringByEvaluatingJavaScriptFromString:str];
28     
29     // 当执行完以上js代码后,就停止动画,并显示网页
30     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
31         [self.displayView stopAnimating];
32         self.webView.scrollView.hidden = NO;
33     });
34 }
  • 结果如下,可以看到标题已经改成鲜花网了:

  2. JS中调用OC方法

  • 在网页中点击一个按钮打开手机相册,这样的需求就需要在js代码中调用oc的方法
  • 可以先在js中布局一个按钮,并写一个函数,当点击按钮时就调用这个函数,函数中一定要传递一个参数,这个参数就包括:协议头(用来识别是谁发送的请求)和方法名,如下代码,协议头是"js:///",要调用的方法名是"openCamera":
 1 <!DOCTYPE html>
 2 <html>
 3 <head lang="en">
 4     <meta charset="UTF-8">
 5     <title>打开相册</title>
 6     <style>
 7         body{
 8             padding: 30px;
 9         }
10     </style>
11 </head>
12 <body>
13    <button onclick="openCamera();">打开相册</button>
14    <script type="text/javascript">
15        // 内置对象 window
16        function openCamera(){
17            window.location.href = 'js:///openCamera';
18        }
19    </script>
20 </body>
21 </html>
  • 此时JS代码已经完成,再到OC中解析,在这个方法中webView:shouldStartLoadWithRequest:navigationType:获取JS传递过来的参数,并解析它,将方法名截取出来,调用该方法
 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     NSURL *url = [[NSBundle mainBundle] URLForResource:@"openCamera" withExtension:@"html"];
 4     NSURLRequest *request = [NSURLRequest requestWithURL:url];
 5     [self.webView loadRequest:request];
 6 }
 7 
 8 
 9 // 打开相册
10 - (void)openCamera{
11     UIImagePickerController *vc = [[UIImagePickerController alloc] init];
12     vc.sourceType = UIImagePickerControllerSourceTypePhotoLibrary;
13     [self presentViewController:vc animated:YES completion:nil];
14 }
15 
16 
17 #pragma mark -<UIWebViewDelegate>
18 
19 - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType{
20     NSString *webUrl = request.URL.absoluteString;
21     NSRange range = [webUrl rangeOfString:@"js:///"];
22     // 获取协议头的第一个字母位置
23     NSUInteger location = range.location;
24    
25     // 如果协议正确
26     if (location != NSNotFound) {
27         // 从协议头最后一个字母开始,全部转为字符串(拿到方法名)
28         NSString *str = [webUrl substringFromIndex:location + range.length];
29         // 将字符串转为selector,并给self调用
30         SEL open = NSSelectorFromString(str);
31         [self performSelector:open];
32     }
33     return YES;
34 }
原文地址:https://www.cnblogs.com/heyode/p/5195181.html