前言:说起JS交互,很多童鞋会黯然色变,感觉很高深的样子。大部分小伙伴只知道一种,哪一种我也说说吧。

   1.在webView中将要请求的时候,拦截URL,进行重定向,然而该场景实用有限,网上资料也很多下面说说另一种交互方式。

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

  2.先说一下这种交互方式应用的场景吧。

     2.1:需求:假如贵公司在做一个金融项目,有一个版本功能需要提交个人资料信息,只是为了一个业务需要,那么通过h5做一套,然后iOS和Android只需要webView加载就行,明显提高了开发效率。。。如果贵公司的其他产品也想接入这个功能,那也能通过webview方式直接用了,所谓是牛逼哄哄,通用性特别强。

         但是:(1):比如,webview里有一个上传身份证照片的功能,点击网页,需要iOS端调起相册功能。。如何交互??

                    (2): 加载的网页中,点击一个按钮,要查看订单详情功能,但是需要传会订单号,怎么办:

                    (3): 点击下一步,,iOS端进入下一个界面;??

  这就牵扯到JS调用OC方法,传递参数等等。

 

3.本文将非常详细的说明使用方法,一句代码不少的说明,你只需要按照步骤操作,一定能运行出你想要的JS交互场景,包你能派上大用场。。废话不说了,开始吧

 

正文:JS交互,就是js 中通过一个对象来调用方法的

   1.js交互,首先我们要准备一个html文件,没有网页文件,要不然怎么交互:至于这些东西怎么创建,这里不做介绍,楼主最后会附上联系方式,提供demo,demo中有,直接复制就行。

   1.1.首先准备一个html文件,html文件里引用了外部的JS文件

 

iOS webView的高级用法之JS交互_webview

2.js文件,里面实现了html文件里的一些按钮的点击事件

iOS webView的高级用法之JS交互_webview_02

 

图片里非常清楚的注释了一些重要代码的注释,非常详细,搞得自己很会h5一样,程序员,不能放弃任何一次装b的机会,

 

⚠️注意: 这里在网页中写了4个按钮,,分别调OC的方法

                   1. 点击按钮,唤起系统相册功能;

                   2. 就是简单的调一个方法

                   3. 调用一个参数的方法

                   4. 调用多个参数的方法,这里举例是两个。

 

  2.首先创建一个类 继承NSObject ,并且规定一个协议,直接上代码

 2.1>创建TestJSObject.h头文件

#import <Foundation/Foundation.h>
#import <JavaScriptCore/JavaScriptCore.h>

@protocol TestJSObjectProtocol <JSExport>
/// 调支付
- (void)ZTHpay;
/// 调系统相册
- (void)ZTHShowPicker;
/// 传参数回来 比如是一个订单号
- (void)ZTHPassParameter:(NSString *)orderNumber;
/// 传两个参数回来 比如是订单号,姓名
- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name;
@end


@interface TestJSObject : NSObject<TestJSObjectProtocol>
///定义三种block,回调到控制器中;
@property (nonatomic,copy)void(^showPickerBlock)();

@end

2.2:然后在.m中实现声明的方法,这4个方法,都会被调用

#import "TestJSObject.h"
@implementation TestJSObject
- (void)ZTHpay{
NSLog(@"调了支付了-----------------");
}
- (void)ZTHShowPicker{
NSLog(@"调了相机-------------------");
dispatch_async(dispatch_get_main_queue(), ^{
//当然回调后要处理的逻辑,肯定不能在这个类里处理,这里采用block回调到控制器中处理,其余的三种方式都可以用这种方式处理,这里就不一一列举了
self.showPickerBlock();
});
}
- (void)ZTHPassParameter:(NSString *)orderNumber{
NSLog(@"%@", orderNumber);
}
//- (void)ZTHTestParameterone:(NSString *)orderNumber AndParametertwo:(NSString *)name{
// NSLog(@"订单号--%@姓名---%@", orderNumber, name);
//}
- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name{
NSLog(@"订单号--%@姓名---%@", orderNumber, name);
}
@end

  3最后在控制器中

   3.1>在懒加载中,设置了web view的url,是一个本地文件,也就是我们一开始写的html文件的路径。

#pragma mark - lazy
- (UIWebView *)webview{
if (!_webview) {
_webview=[[UIWebViewalloc]initWithFrame:CGRectMake(0,200,self.view.bounds.size.width,300)];
_webview.delegate =self;
_webview.backgroundColor=[UIColorlightGrayColor];
NSString *htmlPath = [[NSBundlemainBundle]pathForResource:@"index"ofType:@"html"];
NSURL *localUrl = [[NSURLalloc]initFileURLWithPath:htmlPath];
[_webview loadRequest:[NSURLRequestrequestWithURL:localUrl]];
}
return _webview;
}
3.2.
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//首先创建JSContext对象(此处通过当前webView的键获取到jscontext)
_context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

//第二种情况,js是通过对象调用的,我们假设js里面有一个对象 testobject 在调用方法
//首先创建我们新建类的对象,将他赋值给js的对象
TestJSObject *testJO=[TestJSObjectnew];
testJO.showPickerBlock = ^{
[selfshowImagePicker];
};
_context[@"testobject"]=testJO;
}

到这里,就已经大功告成了。。。文中打红色的文字部分需要您仔细欣赏欣赏,,首先在TestJSObject.h中,我们声明了一个block属性,原因JS调用的方法实现在改类中,但是我们不能在这个类里处理逻辑,那当然需要一个属性回调到控制器中咯,于是在实现中调用了block,然后在上面写了block的实体,去调用

showImagePicker方法,然后你就可以处理了,,,,其实就是block最简单的用法,,但是,,肯定有很多童鞋不了解。。哈哈,不耽误。。下面附上控制器的所有代码,

//  Copyright © 2016年朱同海. All rights reserved.
// 本文主要介绍JS调用OC交互的方式

#import "ViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>
#import "TestJSObject.h"

@interface ViewController () <UIWebViewDelegate,UIActionSheetDelegate>
{
JSContext *_context;
}
@property (nonatomic,strong)UIWebView *webview;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColorcyanColor];
[self.viewaddSubview:self.webview];
}
#pragma mark - lazy
- (UIWebView *)webview{
if (!_webview) {
_webview=[[UIWebViewalloc]initWithFrame:CGRectMake(0,200,self.view.bounds.size.width,300)];
_webview.delegate =self;
_webview.backgroundColor=[UIColorlightGrayColor];
NSString *htmlPath = [[NSBundlemainBundle]pathForResource:@"index"ofType:@"html"];
NSURL *localUrl = [[NSURLalloc]initFileURLWithPath:htmlPath];
[_webview loadRequest:[NSURLRequestrequestWithURL:localUrl]];
}
return _webview;
}
#pragma mark - UIWebViewDelegate
- (void)webViewDidFinishLoad:(UIWebView *)webView{
//首先创建JSContext对象(此处通过当前webView的键获取到jscontext)
_context=[webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];

//第二种情况,js是通过对象调用的,我们假设js里面有一个对象 testobject 在调用方法
//首先创建我们新建类的对象,将他赋值给js的对象
TestJSObject *testJO=[TestJSObjectnew];
testJO.showPickerBlock = ^{
[self showImagePicker];
};
_context[@"testobject"]=testJO;
}
- (void)showImagePicker{
NSLog(@"开始唤起相机");
UIActionSheet *actionSheet = [[UIActionSheetalloc]
initWithTitle:@"请选择文件来源"
delegate:self
cancelButtonTitle:@"取消"
destructiveButtonTitle:nil
otherButtonTitles:@"拍照",@"从手机相册选择",nil];
[actionSheet showInView:self.view];
}
@end

 

4.上一些运行图吧

  4.1:web view的界面图;;

iOS webView的高级用法之JS交互_webview_03

 

4.2,点击第一个按钮,通过调

ZTHShowPicker方法,内部block的调用,唤起控制器中actionsheet。

iOS webView的高级用法之JS交互_webview_04

4.3,点击最后两个按钮,,第一个传递订单号,第二个传递订单号和姓名,点了两次,打印了两次

iOS webView的高级用法之JS交互_javascript_05

 

5.关于带多个参数的JS回调,OC中对应方法的写法:

 比如JS中定义了这个方法

 

 testobject.ZTHTestParameteroneAndParametertwo("1123425255","ZTH");那ZTHTestParameteroneAndParametertwo为方法名

那么OC中方法名可以这么写:1和2都是可行的

 

1.- (void)ZTHTestParameterone:(NSString *)orderNumber AndParametertwo:(NSString *)name;

2.- (void)ZTHTestParameteroneAnd:(NSString *)orderNumber Parametertwo:(NSString *)name;

聪明的你看出来了,只要是OC的方法名去掉:(冒号)拼接起来后,,和JS的方法名一致,那么都是会调用改方法的

 

千万不能作死:说,我这么拼也是我上面说的原理,那么很遗憾的告诉你,不可以,你把And拆开了,是一个单词,不识别(个人见解)

3.- (void)ZTHTestParameteroneA:(NSString *)orderNumberndParametertwo:(NSString *)name;

最后说两句:这可能是JS交互中最好用的方法了,总结一下也就是我们在OC中定义一个遵守

JSExport协议的类,又定义了一个协议,声明实现的方法和js中按钮的点击事件方法名称一致,用来一一映射。。最后在控制器中webview加载完毕之后,

 

TestJSObject *testJO=[TestJSObjectnew];
testJO.showPickerBlock = ^{
[selfshowImagePicker];
};
_context[@"testobject"]=testJO;

当然OC内部肯定封装了很多东西匹配他们,,这不用我们管,,最后我们看看JS文件中的一个方法名

 

 testobject.ZTHpay();

原来是根据testobject这个对象联系起来的,

楼主语言能力不行,不知道有没有绕晕你,但是你只要把demo跑一跑,问题就都能解决了。。当然你要是知道点h5的东西,那肯定更简单咯

 

就先写到这,回头再完善

当然楼主也不是凭空就会的,本文参考链接,当时他说的是技术点,我把细节说的很细,结合下更好哦。