工作中遇到的JS交互问题,稍微整理一下,留下来以备以后查用
JavaScriptCore.framework提供两种方法交互方法,
一种是基于block的交互,
一种是基于协议的交互
0.导入JavaScriptCore.framework(就是在building phases里添加库)
基于协议实现的JS与webView交互
1.定义协议,示例代码如下:
// ZSJSDelegate.h
#import <JavaScriptCore/JavaScriptCore.h>
@protocol ZSJSDelegate <JSExport>
//JS从iOS获取数据
- (NSString *)postInfoFromWebView;
//iOS从JS获取数据
- (void)postInfoFromJS:(NSString *)info;
//iOS从JS获取数据,多参数拼接的情况
- (void)postNameFromJS:(NSString *)name andInfo:(NSString *)info;
@end
2.创建交互对象,遵守上述协议,实现协议方法,示例代码如下:
// ZSJSObject.h
#import <Foundation/Foundation.h>
#import "ZSJSDelegate.h"
@interface ZSJSObject : NSObject
@end
// ZSJSObject.m
#import "ZSJSObject.h"
@interface ZSJSObject ()<ZSJSDelegate>
@end
@implementation ZSJSObject
- (NSString *)postInfoFromWebView
{
return @"infoForm_iOS";
}
- (void)postInfoFromJS:(NSString *)info
{
NSLog(@"info:%@", info);
}
- (void)postNameFromJS:(NSString *)name andInfo:(NSString *)info
{
NSLog(@"name:%@, info:%@", name, info);
}
@end
3.在webView中实现交互,示例代码如下:
// ViewController.m
#import "ViewController.h"
#import "ZSJSObject.h"
@interface ViewController ()<UIWebViewDelegate>
@end
@implementation ViewController
{
UIWebView *_webView;
JSContext *_context;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createWebView];
}
- (void)createWebView
{
_webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_webView];
_webView.backgroundColor = [UIColor lightGrayColor];
_webView.delegate = self;
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
//为什么这么写,我也不懂,希望有大神解惑
_context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
_context[@"jsObject"] = [[ZSJSObject alloc]init];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//网页加载完成之后两秒钟,进行JS测试
[self performSelector:@selector(testJS) withObject:nil afterDelay:2.0f];
}
//测试交互,手动写三个JS语句进行调用协议定义的方法
- (void)testJS
{
//JS从iOS获取数据,通过返回值将数据传道JS
[_context evaluateScript:@"alert(jsObject.postInfoFromWebView());"];
//本地从JS获取数据,通过参数将数据传递到iOS
[_context evaluateScript:@"jsObject.postInfoFromJS('infoFromJS');"];
//多个参数拼接的规则:第二个参数名大写首字母
[_context evaluateScript:@"jsObject.postNameFromJSAndInfo('nameFromJS','info');"];
}
基于block实现的JS与iOS交互
【注意】:比协议实现的步骤简单,但是容易出现控制器无法释放的问题,对内存要求不高的可以忽略
直接上示例代码:
// JSWithBlockViewController.m
#import "JSWithBlockViewController.h"
#import <JavaScriptCore/JavaScriptCore.h>
@interface JSWithBlockViewController ()<UIWebViewDelegate>
@end
@implementation JSWithBlockViewController
{
UIWebView *_webView;
JSContext *_context;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
[self createWebView];
}
- (void)createWebView
{
_webView = [[UIWebView alloc]initWithFrame:self.view.bounds];
[self.view addSubview:_webView];
_webView.backgroundColor = [UIColor lightGrayColor];
_webView.delegate = self;
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[_webView loadRequest:request];
//为什么这么写,我也不懂,希望有大神解惑
_context = [_webView valueForKeyPath:@"documentView.webView.mainFrame.javaScriptContext"];
//JS从iOS获取数据的实现
_context[@"postInfoFromWebView"] = ^() {
return @"infoFrom_iOS(block)";
};
//iOS从JS获取数据的实现
_context[@"postInfoFromJS"] = ^() {
NSArray *args = [JSContext currentArguments];
for (JSValue *jsVal in args) {
NSString *str = jsVal.toString;
NSLog(@"arg:%@", str);
}
};
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
//网页加载完成之后两秒钟,进行JS测试
[self performSelector:@selector(testJS) withObject:nil afterDelay:2.0f];
}
//测试交互,手动写三个JS语句进行调用协议定义的方法
- (void)testJS
{
//JS从iOS获取数据,通过返回值将数据传到JS
[_context evaluateScript:@"alert(postInfoFromWebView());"];
//本地从JS获取数据,通过参数将数据传递到iOS
[_context evaluateScript:@"postInfoFromJS('infoFromJS');"];
[_context evaluateScript:@"postInfoFromJS('nameFromJS','info');"];
}
基本上就这些,有什么不妥的可以联系我。